Module: TypedEAVHelper
- Defined in:
- lib/generators/typed_eav/scaffold/templates/helpers/typed_eav_helper.rb
Instance Method Summary collapse
-
#render_array_field(form:, name:, value:, field_method:, field_opts: {}) ⇒ Object
Render an array field with add/remove buttons (Stimulus-powered).
-
#render_typed_eav_form(field:) ⇒ Object
Render the field definition form (for creating/editing field definitions).
-
#render_typed_eav_search(fields:, url:) ⇒ Object
Render a search form for filtering entities by typed fields.
-
#render_typed_value_input(form:, typed_value:, fields_by_id: nil) ⇒ Object
Render a single typed value input.
-
#render_typed_value_inputs(form:, record:) ⇒ Object
Render all typed field inputs for a record’s form.
-
#typed_eav_operator_label(operator) ⇒ Object
─── Operator Labels ────────────────────────────────────────.
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 |