Module: ElaineCrud::RelationshipHandling
- Extended by:
- ActiveSupport::Concern
- Included in:
- BaseController
- Defined in:
- lib/elaine_crud/relationship_handling.rb
Overview
Methods for handling ActiveRecord relationships (belongs_to, has_many) Provides eager loading, filtering, and parent context management
Instance Method Summary collapse
-
#apply_has_many_filtering(records) ⇒ ActiveRecord::Relation
Apply filtering based on parent relationship parameters.
-
#detect_parent_filters ⇒ Hash
Detect parent filter parameters from URL.
-
#find_reflection_by_foreign_key(foreign_key) ⇒ ActiveRecord::Reflection::BelongsToReflection?
Find reflection by foreign key name.
-
#get_all_relationship_includes ⇒ Array<Symbol>
Get list of associations to include for avoiding N+1 queries.
-
#get_belongs_to_includes ⇒ Array<Symbol>
Get list of belongs_to associations to include for avoiding N+1 queries.
-
#get_habtm_includes ⇒ Array<Symbol>
Get has_and_belongs_to_many relationships that need to be included.
-
#get_has_many_includes ⇒ Array<Symbol>
Get has_many relationships that need to be included.
-
#get_has_one_includes ⇒ Array<Symbol>
Get has_one relationships that need to be included.
-
#populate_parent_relationships(record) ⇒ Object
Populate parent relationships from URL parameters.
-
#redirect_after_create_path ⇒ String
Determine redirect path after create based on context.
-
#set_parent_context(parent_field, parent_id) ⇒ Object
Set context for UI display.
-
#valid_parent_filter?(field_name) ⇒ Boolean
Validate that the parent filter is legitimate.
Instance Method Details
#apply_has_many_filtering(records) ⇒ ActiveRecord::Relation
Apply filtering based on parent relationship parameters
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/elaine_crud/relationship_handling.rb', line 118 def apply_has_many_filtering(records) parent_filters = detect_parent_filters parent_filters.each do |parent_field, parent_id| next unless parent_id.present? # Validate that this is a legitimate foreign key if valid_parent_filter?(parent_field) records = records.where(parent_field => parent_id) # Set instance variables for UI context set_parent_context(parent_field, parent_id) end end records end |
#detect_parent_filters ⇒ Hash
Detect parent filter parameters from URL
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/elaine_crud/relationship_handling.rb', line 138 def detect_parent_filters parent_filters = {} # Look for foreign key parameters in the URL crud_model.reflections.each do |name, reflection| next unless reflection.is_a?(ActiveRecord::Reflection::BelongsToReflection) foreign_key = reflection.foreign_key.to_sym param_value = params[foreign_key] if param_value.present? parent_filters[foreign_key] = param_value end end parent_filters end |
#find_reflection_by_foreign_key(foreign_key) ⇒ ActiveRecord::Reflection::BelongsToReflection?
Find reflection by foreign key name
191 192 193 194 195 196 |
# File 'lib/elaine_crud/relationship_handling.rb', line 191 def find_reflection_by_foreign_key(foreign_key) crud_model.reflections.values.find do |reflection| reflection.is_a?(ActiveRecord::Reflection::BelongsToReflection) && reflection.foreign_key.to_sym == foreign_key.to_sym end end |
#get_all_relationship_includes ⇒ Array<Symbol>
Get list of associations to include for avoiding N+1 queries
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/elaine_crud/relationship_handling.rb', line 95 def get_all_relationship_includes return [] unless crud_model includes = [] # Include belongs_to relationships (existing logic) includes += get_belongs_to_includes # Include has_many relationships that are displayed includes += get_has_many_includes # Include has_one relationships that are displayed includes += get_has_one_includes # Include has_and_belongs_to_many relationships that are displayed includes += get_habtm_includes includes.uniq end |
#get_belongs_to_includes ⇒ Array<Symbol>
Get list of belongs_to associations to include for avoiding N+1 queries
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/elaine_crud/relationship_handling.rb', line 16 def get_belongs_to_includes return [] unless crud_model includes = [] # Get all belongs_to relationships that are displayed crud_model.reflections.each do |name, reflection| next unless reflection.is_a?(ActiveRecord::Reflection::BelongsToReflection) foreign_key = reflection.foreign_key.to_sym # Include if this foreign key is in the displayed columns or configured if determine_columns.include?(foreign_key.to_s) || field_configured?(foreign_key) includes << name.to_sym end end includes end |
#get_habtm_includes ⇒ Array<Symbol>
Get has_and_belongs_to_many relationships that need to be included
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/elaine_crud/relationship_handling.rb', line 76 def get_habtm_includes return [] unless crud_model includes = [] crud_model.reflections.each do |name, reflection| next unless reflection.is_a?(ActiveRecord::Reflection::HasAndBelongsToManyReflection) # Include if this relationship is displayed in columns or configured if determine_columns.include?(name) || field_configured?(name.to_sym) includes << name.to_sym end end includes end |
#get_has_many_includes ⇒ Array<Symbol>
Get has_many relationships that need to be included
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/elaine_crud/relationship_handling.rb', line 38 def get_has_many_includes return [] unless crud_model includes = [] crud_model.reflections.each do |name, reflection| next unless reflection.is_a?(ActiveRecord::Reflection::HasManyReflection) # Include if this relationship is displayed in columns or configured if determine_columns.include?(name) || field_configured?(name.to_sym) includes << name.to_sym end end includes end |
#get_has_one_includes ⇒ Array<Symbol>
Get has_one relationships that need to be included
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/elaine_crud/relationship_handling.rb', line 57 def get_has_one_includes return [] unless crud_model includes = [] crud_model.reflections.each do |name, reflection| next unless reflection.is_a?(ActiveRecord::Reflection::HasOneReflection) # Include if this relationship is displayed in columns or configured if determine_columns.include?(name) || field_configured?(name.to_sym) includes << name.to_sym end end includes end |
#populate_parent_relationships(record) ⇒ Object
Populate parent relationships from URL parameters
200 201 202 203 204 205 206 |
# File 'lib/elaine_crud/relationship_handling.rb', line 200 def populate_parent_relationships(record) detect_parent_filters.each do |foreign_key, parent_id| if valid_parent_filter?(foreign_key) && record.public_send(foreign_key).blank? record.public_send("#{foreign_key}=", parent_id) end end end |
#redirect_after_create_path ⇒ String
Determine redirect path after create based on context
210 211 212 213 214 215 216 217 218 |
# File 'lib/elaine_crud/relationship_handling.rb', line 210 def redirect_after_create_path if @parent_context # Redirect back to filtered index view polymorphic_path([crud_model], @parent_context[:foreign_key] => @parent_context[:record].id) else # Standard redirect to show page polymorphic_path(@record) end end |
#set_parent_context(parent_field, parent_id) ⇒ Object
Set context for UI display
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/elaine_crud/relationship_handling.rb', line 167 def set_parent_context(parent_field, parent_id) reflection = find_reflection_by_foreign_key(parent_field) return unless reflection begin parent_record = reflection.klass.find(parent_id) @parent_context = { record: parent_record, relationship_name: reflection.name, foreign_key: parent_field, model_class: reflection.klass } rescue ActiveRecord::RecordNotFound @parent_context = { error: "#{reflection.klass.name} with ID #{parent_id} not found", foreign_key: parent_field, model_class: reflection.klass } end end |
#valid_parent_filter?(field_name) ⇒ Boolean
Validate that the parent filter is legitimate
159 160 161 162 |
# File 'lib/elaine_crud/relationship_handling.rb', line 159 def valid_parent_filter?(field_name) crud_model.column_names.include?(field_name.to_s) && field_name.to_s.end_with?('_id') end |