Module: TypedEAVHelper

Defined in:
lib/generators/typed_eav/scaffold/templates/helpers/typed_eav_helper.rb

Instance Method Summary collapse

Instance Method Details

#render_array_field(form:, name:, value:, field_method:, field_opts: {}) ⇒ Object

Render an array field with add/remove buttons (Stimulus-powered).

<%= render_array_field(form: f, name: :value, value: [1,2,3],
      field_method: :number_field, field_opts: { min: 0 }) %>


74
75
76
77
78
79
80
81
82
# File 'lib/generators/typed_eav/scaffold/templates/helpers/typed_eav_helper.rb', line 74

def render_array_field(form:, name:, value:, field_method:, field_opts: {})
  render partial: "shared/array_field", locals: {
    form: form,
    name: name,
    value: value,
    field_method: field_method,
    field_opts: field_opts,
  }
end

#render_typed_eav_form(field:) ⇒ Object

Render the field definition form (for creating/editing field definitions).



87
88
89
90
# File 'lib/generators/typed_eav/scaffold/templates/helpers/typed_eav_helper.rb', line 87

def render_typed_eav_form(field:)
  partial = field_form_partial(field)
  render partial: partial, locals: { field: field }
end

#render_typed_eav_search(fields:, url:) ⇒ Object

Render a search form for filtering entities by typed fields.

<%= render_typed_eav_search(fields: Contact.typed_eav_definitions, url: contacts_path) %>


98
99
100
101
102
103
# File 'lib/generators/typed_eav/scaffold/templates/helpers/typed_eav_helper.rb', line 98

def render_typed_eav_search(fields:, url:)
  render partial: "typed_eav/finders/form", locals: {
    fields: fields,
    url: url,
  }
end

#render_typed_value_input(form:, typed_value:, fields_by_id: nil) ⇒ Object

Render a single typed value input. Expects ‘form` to be a typed-value builder (from `fields_for :typed_values`) — it emits the hidden `id` / `field_id` inputs nested attributes need to resolve the row, then delegates to the type-specific partial for the value input itself.

Advanced callers that own their own ‘fields_for` block can invoke this directly:

<%= form.fields_for :typed_values, typed_value do |vf| %>
  <%= render_typed_value_input(form: vf, typed_value: vf.object) %>
<% end %>

Pass ‘fields_by_id:` (a => Field map) when iterating many values to avoid triggering a per-value `typed_value.field` query in the association-loaded-but-`:field`-not-preloaded case.



54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/generators/typed_eav/scaffold/templates/helpers/typed_eav_helper.rb', line 54

def render_typed_value_input(form:, typed_value:, fields_by_id: nil)
  field = (fields_by_id && fields_by_id[typed_value.field_id]) || typed_value.field
  partial_name = value_input_partial(field)

  hidden = "".html_safe
  hidden << form.hidden_field(:id) if typed_value.persisted?
  hidden << form.hidden_field(:field_id, value: field.id)

  hidden + render(partial: partial_name, locals: {
    form: form,
    typed_value: typed_value,
    field: field,
  })
end

#render_typed_value_inputs(form:, record:) ⇒ Object

Render all typed field inputs for a record’s form. Owns the ‘fields_for :typed_values` builder so the submitted params are shaped correctly for `accepts_nested_attributes_for :typed_values`.

<%= render_typed_value_inputs(form: f, record: @contact) %>

The controller’s strong params must permit:

typed_values_attributes: [:id, :field_id, :value, :_destroy,
                          { value: [] }]


17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/generators/typed_eav/scaffold/templates/helpers/typed_eav_helper.rb', line 17

def render_typed_value_inputs(form:, record:)
  # Index the in-scope definitions by id. Used both to look up sort_order
  # without touching `v.field` (avoids per-value field load when typed_values
  # was preloaded but `:field` was not) AND to thread the resolved field
  # into `render_typed_value_input` so it doesn't re-trigger that lookup.
  fields_by_id = record.typed_eav_definitions.index_by(&:id)

  typed_values = record.initialize_typed_values.sort_by do |v|
    # Newly-built values may have field_id=nil but carry an in-memory
    # `field` object; fall back to that to avoid sorting them all to 0.
    field = fields_by_id[v.field_id] || v.field
    field&.sort_order || 0
  end

  parts = typed_values.map do |typed_value|
    form.fields_for(:typed_values, typed_value, child_index: nested_child_index(typed_value)) do |vf|
      render_typed_value_input(form: vf, typed_value: typed_value, fields_by_id: fields_by_id)
    end
  end
  safe_join(parts)
end

#typed_eav_operator_label(operator) ⇒ Object

─── Operator Labels ────────────────────────────────────────



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/generators/typed_eav/scaffold/templates/helpers/typed_eav_helper.rb', line 107

def typed_eav_operator_label(operator)
  {
    eq: "equals",
    not_eq: "does not equal",
    gt: "greater than",
    gteq: "greater than or equal",
    lt: "less than",
    lteq: "less than or equal",
    between: "between",
    contains: "contains",
    not_contains: "does not contain",
    starts_with: "starts with",
    ends_with: "ends with",
    any_eq: "includes",
    all_eq: "includes all",
    is_null: "is empty",
    is_not_null: "is not empty",
  }[operator.to_sym] || operator.to_s.humanize
end