Class: CrudComponents::Fields::BelongsToField

Inherits:
Base
  • Object
show all
Defined in:
lib/crud_components/fields/belongs_to_field.rb

Overview

belongs_to / has_one: nil-safe link via the target’s label. The filter (belongs_to only) accepts both the target’s identify_by value (what the select submits) and free text matched against the target’s search_in —one param, two OR-combined parameterized subqueries.

Constant Summary

Constants inherited from Base

CrudComponents::Fields::Base::NON_EDITABLE_COLUMNS

Instance Attribute Summary

Attributes inherited from Base

#facets, #model, #name, #options

Instance Method Summary collapse

Methods inherited from Base

#apply_filter, #apply_filter_facet, #apply_sort, #column, #custom_header?, #declared_preloads, #editable?, #editable_permitted?, #filter_control, #filter_facet, #filter_includes_null?, #filterable?, #form_partial, #group_label, #header, #header_actions, #human_name, #initialize, #nullable?, #permitted?, #picker_label, #range_filter?, #render_block, #renderer, #renderer_options, #sort_facet, #sortable?, #value

Constructor Details

This class inherits a constructor from CrudComponents::Fields::Base

Instance Method Details

#apply_derived_filter(scope, exact: nil) ⇒ Object



47
48
49
50
51
52
53
# File 'lib/crud_components/fields/belongs_to_field.rb', line 47

def apply_derived_filter(scope, exact: nil, **)
  return scope unless exact

  identified = scope.where(name => target.where(target_structure.identify_by => exact))
  searched = like_subquery(scope, exact)
  searched ? identified.or(searched) : identified
end

#default_editable?Boolean

── forms ────────────────────────────────────────────────────────────Assigned via the foreign key; the select submits real ids (forms are POST bodies, not shareable URLs — unlike the filter, which uses identify_by).

Returns:

  • (Boolean)


72
# File 'lib/crud_components/fields/belongs_to_field.rb', line 72

def default_editable? = reflection.belongs_to? && !reflection.polymorphic?

#default_rendererObject



8
# File 'lib/crud_components/fields/belongs_to_field.rb', line 8

def default_renderer = :association

#derived_filter_controlObject

select (a dropdown of all targets) below ‘select_limit` rows, else free text. Counted per render, not memoized: the field instance lives on the process-cached Structure, so a memoized count would freeze at its boot-time value and render the wrong control once the table grows past the limit. One COUNT per filter-row render is negligible next to rendering the table.



37
38
39
# File 'lib/crud_components/fields/belongs_to_field.rb', line 37

def derived_filter_control
  target.count <= CrudComponents.config.select_limit ? :select : :text
end

#derived_filterable?Boolean

Returns:

  • (Boolean)


26
27
28
# File 'lib/crud_components/fields/belongs_to_field.rb', line 26

def derived_filterable?
  reflection.belongs_to? && !reflection.polymorphic?
end

#derived_sortable?Boolean

Returns:

  • (Boolean)


30
# File 'lib/crud_components/fields/belongs_to_field.rb', line 30

def derived_sortable? = false

#eager_loadObject

Load the association, nesting the target’s identity_preloads (its label’s own association deps) plus any per-column ‘preload:` so the target’s label never N+1s. e.g. { order: %i[customer training] }. A polymorphic belongs_to has no single target class, so we can’t nest its label’s preloads — just preload the association itself (Rails groups it by type); the cell still renders each record’s label and links it at runtime.



61
62
63
64
65
66
# File 'lib/crud_components/fields/belongs_to_field.rb', line 61

def eager_load
  return [name] if reflection.polymorphic?

  nested = (target_structure.identity_preloads + declared_preloads).uniq
  [nested.empty? ? name : { name => nested }]
end

#filter_choices(_query = nil) ⇒ Object



41
42
43
44
45
# File 'lib/crud_components/fields/belongs_to_field.rb', line 41

def filter_choices(_query = nil)
  structure = target_structure
  target.all.map { |record| [structure.label_for(record).to_s, record.public_send(structure.identify_by)] }
        .sort_by(&:first)
end

#form_choicesObject



76
77
78
79
# File 'lib/crud_components/fields/belongs_to_field.rb', line 76

def form_choices
  structure = target_structure
  target.all.map { |record| [structure.label_for(record).to_s, record.id] }.sort_by(&:first)
end

#form_controlObject



73
# File 'lib/crud_components/fields/belongs_to_field.rb', line 73

def form_control = :belongs_to

#group_modelObject

Picker grouping: a belongs_to/has_one column anchors its target’s group (polymorphic has no single target, so it groups under its own model).



20
# File 'lib/crud_components/fields/belongs_to_field.rb', line 20

def group_model = reflection.polymorphic? ? model : target

#permit_paramObject



74
# File 'lib/crud_components/fields/belongs_to_field.rb', line 74

def permit_param = reflection.foreign_key.to_sym

#reflectionObject



10
11
12
# File 'lib/crud_components/fields/belongs_to_field.rb', line 10

def reflection
  @reflection ||= model.reflect_on_association(name)
end

#targetObject



14
15
16
# File 'lib/crud_components/fields/belongs_to_field.rb', line 14

def target
  reflection.klass
end

#target_structureObject



22
23
24
# File 'lib/crud_components/fields/belongs_to_field.rb', line 22

def target_structure
  Structure.for(target)
end