Class: Avo::Fields::BelongsToField
- Includes:
- Concerns::IsSearchable, Concerns::UseResource
- Defined in:
- lib/avo/fields/belongs_to_field.rb
Overview
Requirements
- list
- ID
- label
- Type
- foreign_key
- foreign_key for poly type
- foreign_key for poly id
- is_disabled?
Defined Under Namespace
Classes: EditComponent, IndexComponent, ShowComponent
Constant Summary
Constants included from Concerns::HasResizableEditor
Concerns::HasResizableEditor::COMPATIBLE_EDITOR_SELECTORS
Instance Attribute Summary collapse
-
#allow_via_detaching ⇒ Object
readonly
Returns the value of attribute allow_via_detaching.
-
#attach_scope ⇒ Object
readonly
Returns the value of attribute attach_scope.
-
#link_to_child_resource ⇒ Object
readonly
Returns the value of attribute link_to_child_resource.
-
#link_to_record ⇒ Object
readonly
Returns the value of attribute link_to_record.
-
#polymorphic_as ⇒ Object
readonly
Returns the value of attribute polymorphic_as.
-
#polymorphic_help ⇒ Object
readonly
Returns the value of attribute polymorphic_help.
-
#target ⇒ Object
Returns the value of attribute target.
-
#types ⇒ Object
readonly
for Polymorphic associations.
Attributes inherited from BaseField
#action, #autocomplete, #block, #computable, #computed, #computed_value, #copyable, #default, #for_attribute, #for_presentation_only, #format_display_using, #format_edit_using, #format_form_using, #format_index_using, #format_new_using, #format_show_using, #format_using, #id, #label_help, #null_values, #nullable, #panel_name, #readonly, #record, #required, #size, #sortable, #stacked, #summarizable, #user, #width
Attributes included from Concerns::IsDisabled
Attributes included from Concerns::HasHTMLAttributes
Attributes included from Concerns::VisibleInDifferentViews
#show_on_edit, #show_on_index, #show_on_new, #show_on_preview, #show_on_show
Attributes included from Concerns::IsVisible
Attributes included from Concerns::IsResourceItem
Instance Method Summary collapse
-
#can_create?(final_target_resource = target_resource) ⇒ Boolean
field :user, as: :belongs_to, can_create: true Only can create when: -
can_create: trueoption is present - target resource's policy allow creation (UserPolicy in this example). - #database_id ⇒ Object
- #database_value ⇒ Object
- #default_name ⇒ Object
- #default_placeholder ⇒ Object
-
#field_label ⇒ Object
What the user sees in the text field.
-
#field_value ⇒ Object
The value.
- #fill_field(record, key, value, params) ⇒ Object
- #foreign_key ⇒ Object
- #form_field_label ⇒ Object
- #get_record ⇒ Object
- #id_input_foreign_key ⇒ Object
- #index_link_to_record ⇒ Object
- #index_link_to_resource ⇒ Object
-
#initialize(id, **args, &block) ⇒ BelongsToField
constructor
A new instance of BelongsToField.
- #is_polymorphic? ⇒ Boolean
- #label ⇒ Object
- #options ⇒ Object
- #polymorphic_form_field_label ⇒ Object
-
#reflection ⇒ Object
Get the model reflection instance.
- #reflection_for_key(key) ⇒ Object
- #relation_model_class ⇒ Object
- #target_resource(record: @record, polymorphic_model_class: value&.class) ⇒ Object
- #to_permitted_param ⇒ Object
- #type_input_foreign_key ⇒ Object
- #valid_polymorphic_class(possible_class) ⇒ Object
- #value ⇒ Object
- #values_for_type(model = nil) ⇒ Object
-
#visible_in_reflection?(reflection = nil) ⇒ Boolean
When displayed inside a has_one/has_many reflection, hide this field if it points back to the parent record (i.e., it is the inverse of the reflection).
Methods included from Concerns::UseResource
Methods included from Concerns::IsSearchable
Methods inherited from BaseField
#apply_update_using, #assign_value, #attribute_id, #custom?, #custom_name?, #execute_context, #has_attribute?, #has_own_panel?, #help, #hidden_in_reflection?, #meta, #name, #name_override, #options_for_filter, #parent, #placeholder, #plural_name, #record_errors, #resolve_attribute, #resource_scoped_translation_key, #sentence_name, #shared_translation_key, #table_header_class, #table_header_label, #translated_name, #translated_plural_name, #translation_key, #type, #updatable, #width_class, #width_option
Methods included from Concerns::DomId
Methods included from Concerns::UseViewComponents
#component_for_view, #view_component_name, #view_component_namespace
Methods included from Concerns::IsRequired
Methods included from Concerns::IsDisabled
Methods included from Concerns::IsReadonly
Methods included from Concerns::HasResizableEditor
#resizable_editor?, #resizable_editor_target_selector
Methods included from Concerns::HasHTMLAttributes
Methods included from Concerns::HasDefault
Methods included from Concerns::HasHelpers
Methods included from Concerns::VisibleInDifferentViews
#except_on, #hide_on, #initialize_views, #only_on, #post_initialize, #show_on, #show_on_create, #show_on_update, #visible_in_view?
Methods included from Concerns::IsVisible
Methods included from Concerns::HasItemType
#is_card?, #is_collaboration?, #is_field?, #is_header?, #is_heading?, #is_panel?, #is_sidebar?, #is_tab?, #is_tab_group?, #is_tool?
Methods included from Concerns::IsResourceItem
Methods included from Concerns::Hydration
Constructor Details
#initialize(id, **args, &block) ⇒ BelongsToField
Returns a new instance of BelongsToField.
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/avo/fields/belongs_to_field.rb', line 73 def initialize(id, **args, &block) super @searchable = (args[:searchable] == true || args[:searchable].is_a?(Hash)) ? args[:searchable] : false @polymorphic_as = args[:polymorphic_as] @types = args[:types] @relation_method = attribute_id.to_s.parameterize.underscore @allow_via_detaching = args[:allow_via_detaching] == true @attach_scope = args[:attach_scope] @polymorphic_help = args[:polymorphic_help] @target = args[:target] @use_resource = args[:use_resource] || nil @can_create = args[:can_create].nil? || args[:can_create] @link_to_record = args[:link_to_record].present? ? args[:link_to_record] : false @link_to_child_resource = args[:link_to_child_resource] end |
Instance Attribute Details
#allow_via_detaching ⇒ Object (readonly)
Returns the value of attribute allow_via_detaching.
67 68 69 |
# File 'lib/avo/fields/belongs_to_field.rb', line 67 def allow_via_detaching @allow_via_detaching end |
#attach_scope ⇒ Object (readonly)
Returns the value of attribute attach_scope.
68 69 70 |
# File 'lib/avo/fields/belongs_to_field.rb', line 68 def attach_scope @attach_scope end |
#link_to_child_resource ⇒ Object (readonly)
Returns the value of attribute link_to_child_resource.
71 72 73 |
# File 'lib/avo/fields/belongs_to_field.rb', line 71 def link_to_child_resource @link_to_child_resource end |
#link_to_record ⇒ Object (readonly)
Returns the value of attribute link_to_record.
70 71 72 |
# File 'lib/avo/fields/belongs_to_field.rb', line 70 def link_to_record @link_to_record end |
#polymorphic_as ⇒ Object (readonly)
Returns the value of attribute polymorphic_as.
65 66 67 |
# File 'lib/avo/fields/belongs_to_field.rb', line 65 def polymorphic_as @polymorphic_as end |
#polymorphic_help ⇒ Object (readonly)
Returns the value of attribute polymorphic_help.
69 70 71 |
# File 'lib/avo/fields/belongs_to_field.rb', line 69 def polymorphic_help @polymorphic_help end |
#target ⇒ Object
Returns the value of attribute target.
63 64 65 |
# File 'lib/avo/fields/belongs_to_field.rb', line 63 def target @target end |
#types ⇒ Object (readonly)
for Polymorphic associations
66 67 68 |
# File 'lib/avo/fields/belongs_to_field.rb', line 66 def types @types end |
Instance Method Details
#can_create?(final_target_resource = target_resource) ⇒ Boolean
field :user, as: :belongs_to, can_create: true Only can create when:
- `can_create: true` option is present
- target resource's policy allow creation (UserPolicy in this example)
305 306 307 |
# File 'lib/avo/fields/belongs_to_field.rb', line 305 def can_create?(final_target_resource = target_resource) @can_create && final_target_resource..(:create, raise_exception: false) end |
#database_id ⇒ Object
240 241 242 243 244 245 246 247 |
# File 'lib/avo/fields/belongs_to_field.rb', line 240 def database_id # If the field is a polymorphic value, return the polymorphic_type as key and pre-fill the _id in fill_field. return :"#{polymorphic_as}_type" if polymorphic_as.present? foreign_key rescue attribute_id end |
#database_value ⇒ Object
135 136 137 138 139 |
# File 'lib/avo/fields/belongs_to_field.rb', line 135 def database_value target_resource.id rescue nil end |
#default_name ⇒ Object
279 280 281 282 283 |
# File 'lib/avo/fields/belongs_to_field.rb', line 279 def default_name return polymorphic_as.to_s.humanize if polymorphic_as.present? super end |
#default_placeholder ⇒ Object
90 91 92 |
# File 'lib/avo/fields/belongs_to_field.rb', line 90 def default_placeholder I18n.t("avo.choose_an_option") end |
#field_label ⇒ Object
What the user sees in the text field
112 113 114 |
# File 'lib/avo/fields/belongs_to_field.rb', line 112 def field_label label end |
#field_value ⇒ Object
The value
105 106 107 108 109 |
# File 'lib/avo/fields/belongs_to_field.rb', line 105 def field_value value.send(database_value) rescue nil end |
#fill_field(record, key, value, params) ⇒ Object
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/avo/fields/belongs_to_field.rb', line 201 def fill_field(record, key, value, params) return record unless record.methods.include? key.to_sym if polymorphic_as.present? valid_model_class = valid_polymorphic_class params[:"#{polymorphic_as}_type"] record.send(:"#{polymorphic_as}_type=", valid_model_class) # If the type is blank, reset the id too. id_from_param = params["#{polymorphic_as}_id"] if valid_model_class.blank? || id_from_param.blank? record.send(:"#{polymorphic_as}_id=", nil) else target = target_resource(record:, polymorphic_model_class: value.safe_constantize) record_id = target.find_record(id_from_param, query: scoped_target_query(target, record, for_find: true)).id record.send(:"#{polymorphic_as}_id=", record_id) end else target = target_resource(record:) record_id = if value.blank? value else target.find_record(value, query: scoped_target_query(target, record, for_find: true)).send(reflection.association_primary_key) end record.send(:"#{key}=", record_id) end record end |
#foreign_key ⇒ Object
161 162 163 164 165 166 167 168 169 |
# File 'lib/avo/fields/belongs_to_field.rb', line 161 def foreign_key @foreign_key ||= if polymorphic_as.present? polymorphic_as elsif @record.present? get_model_class(@record).reflections[@relation_method].foreign_key elsif @resource.present? && @resource.model_class.reflections[@relation_method].present? @resource.model_class.reflections[@relation_method].foreign_key end end |
#form_field_label ⇒ Object
309 310 311 |
# File 'lib/avo/fields/belongs_to_field.rb', line 309 def form_field_label "#{id}_id" end |
#get_record ⇒ Object
275 276 277 |
# File 'lib/avo/fields/belongs_to_field.rb', line 275 def get_record @record || @resource.record end |
#id_input_foreign_key ⇒ Object
147 148 149 150 151 152 153 |
# File 'lib/avo/fields/belongs_to_field.rb', line 147 def id_input_foreign_key if is_polymorphic? "#{foreign_key}_id" else foreign_key end end |
#index_link_to_record ⇒ Object
293 294 295 296 297 298 299 |
# File 'lib/avo/fields/belongs_to_field.rb', line 293 def index_link_to_record if @link_to_record.present? get_record else value end end |
#index_link_to_resource ⇒ Object
285 286 287 288 289 290 291 |
# File 'lib/avo/fields/belongs_to_field.rb', line 285 def index_link_to_resource if @link_to_record.present? @resource else target_resource end end |
#is_polymorphic? ⇒ Boolean
155 156 157 158 159 |
# File 'lib/avo/fields/belongs_to_field.rb', line 155 def is_polymorphic? polymorphic_as.present? rescue false end |
#label ⇒ Object
188 189 190 191 |
# File 'lib/avo/fields/belongs_to_field.rb', line 188 def label return if target_resource.blank? target_resource.new(record: value)&.record_title end |
#options ⇒ Object
116 117 118 |
# File 'lib/avo/fields/belongs_to_field.rb', line 116 def values_for_type end |
#polymorphic_form_field_label ⇒ Object
313 314 315 |
# File 'lib/avo/fields/belongs_to_field.rb', line 313 def polymorphic_form_field_label "#{id}_type" end |
#reflection ⇒ Object
Get the model reflection instance
178 179 180 181 182 |
# File 'lib/avo/fields/belongs_to_field.rb', line 178 def reflection reflection_for_key(attribute_id) rescue nil end |
#reflection_for_key(key) ⇒ Object
171 172 173 174 175 |
# File 'lib/avo/fields/belongs_to_field.rb', line 171 def reflection_for_key(key) get_model_class(get_record).reflections[key.to_s] rescue nil end |
#relation_model_class ⇒ Object
184 185 186 |
# File 'lib/avo/fields/belongs_to_field.rb', line 184 def relation_model_class @resource.model_class end |
#target_resource(record: @record, polymorphic_model_class: value&.class) ⇒ Object
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/avo/fields/belongs_to_field.rb', line 249 def target_resource(record: @record, polymorphic_model_class: value&.class) @target_resource ||= if use_resource.present? use_resource elsif is_polymorphic? if polymorphic_model_class.present? get_resource_by_model_class(polymorphic_model_class) else return nil end else reflection_key = polymorphic_as || attribute_id reflection_object = record.class.reflect_on_association(reflection_key) if (link_to_child_resource || @resource&.link_to_child_resource) && value.present? get_resource_by_model_class(value.class.to_s) elsif reflection_object.klass.present? get_resource_by_model_class(reflection_object.klass.to_s) elsif reflection_object.[:class_name].present? get_resource_by_model_class(reflection_object.[:class_name]) else App.get_resource_by_name reflection_key end end end |
#to_permitted_param ⇒ Object
193 194 195 196 197 198 199 |
# File 'lib/avo/fields/belongs_to_field.rb', line 193 def to_permitted_param if polymorphic_as.present? return [:"#{polymorphic_as}_type", :"#{polymorphic_as}_id"] end foreign_key.to_sym end |
#type_input_foreign_key ⇒ Object
141 142 143 144 145 |
# File 'lib/avo/fields/belongs_to_field.rb', line 141 def type_input_foreign_key if is_polymorphic? "#{foreign_key}_type" end end |
#valid_polymorphic_class(possible_class) ⇒ Object
234 235 236 237 238 |
# File 'lib/avo/fields/belongs_to_field.rb', line 234 def valid_polymorphic_class(possible_class) types.find do |type| type.to_s == possible_class.to_s end end |
#value ⇒ Object
94 95 96 97 98 99 100 101 102 |
# File 'lib/avo/fields/belongs_to_field.rb', line 94 def value if is_polymorphic? # Get the value from the pre-filled association record super(polymorphic_as) else # Get the value from the pre-filled association record super(@relation_method) end end |
#values_for_type(model = nil) ⇒ Object
120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/avo/fields/belongs_to_field.rb', line 120 def values_for_type(model = nil) resource = target_resource resource = Avo.resource_manager.get_resource_by_model_class model if model.present? query = scoped_target_query(resource, get_record) lookup_list_limit = Avo.configuration.associations[:lookup_list_limit] query.all.limit(lookup_list_limit).map do |record| [resource.new(record: record).record_title, record.to_param] end.tap do || << t("avo.more_records_available") if .size == lookup_list_limit end end |
#visible_in_reflection?(reflection = nil) ⇒ Boolean
When displayed inside a has_one/has_many reflection, hide this field if it points back to the parent record (i.e., it is the inverse of the reflection). This mirrors the filtering logic in Avo::Concerns::HasItems#get_fields.
320 321 322 323 324 325 326 327 328 329 330 |
# File 'lib/avo/fields/belongs_to_field.rb', line 320 def visible_in_reflection?(reflection = nil) return true if reflection.nil? return true unless respond_to?(:foreign_key) return true unless reflection.inverse_of.present? return true unless reflection.inverse_of.respond_to?(:foreign_key) inverse_fk = reflection.inverse_of.foreign_key self_fk = is_polymorphic? ? self.reflection&.foreign_key : foreign_key inverse_fk != self_fk end |