Module: ActiveRecordCustomPreloader::WithMultipleForeignKeysLoading

Extended by:
ActiveSupport::Concern
Defined in:
lib/active_record_custom_preloader/with_multiple_foreign_keys_loading.rb

Instance Method Summary collapse

Instance Method Details

#association_foreign_keys(assoc_record) ⇒ Object

association records are grouped by return value of this method. it should match returns array of keys for association record to match parent record



57
58
59
# File 'lib/active_record_custom_preloader/with_multiple_foreign_keys_loading.rb', line 57

def association_foreign_keys(assoc_record)
  association_foreign_keys_names.map { |name| assoc_record.public_send(name) }
end

#associations_by_record(grouped_associations, parent_record) ⇒ Object

returns associations for provided parent_record. array for has_many and model or nil for has_one.



63
64
65
66
# File 'lib/active_record_custom_preloader/with_multiple_foreign_keys_loading.rb', line 63

def associations_by_record(grouped_associations, parent_record)
  associations = grouped_associations[record_foreign_keys(parent_record)]
  to_many ? associations || [] : associations&.first
end

#associations_scopeObject

default scope for association records. you can override it for example to preload some values to association records.



70
71
72
# File 'lib/active_record_custom_preloader/with_multiple_foreign_keys_loading.rb', line 70

def associations_scope
  model_class_name.constantize.all
end

#fetch_association(parent_records) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/active_record_custom_preloader/with_multiple_foreign_keys_loading.rb', line 74

def fetch_association(parent_records)
  keys = parent_records.map(&method(:record_foreign_keys)).compact
  condition_part = association_foreign_keys_names.map { |name| "#{name} = ?" }.join(' AND ')
  conditions = []
  keys.size.times { conditions.push(condition_part) }
  condition_sql = conditions.map { |condition| "(#{condition})" }.join(' OR ')
  condition_bindings = keys.flatten
  return {} if condition_sql.blank? || condition_bindings.empty?
  associations = associations_scope.where(condition_sql, *condition_bindings).to_a
  associations.group_by(&method(:association_foreign_keys))
end

#preload(parent_records) ⇒ Object



86
87
88
89
90
91
92
# File 'lib/active_record_custom_preloader/with_multiple_foreign_keys_loading.rb', line 86

def preload(parent_records)
  grouped_associations = fetch_association(parent_records)
  parent_records.each do |parent_record|
    value = associations_by_record(grouped_associations, parent_record)
    parent_record._set_custom_preloaded_value(name, value)
  end
end

#record_foreign_keys(parent_record) ⇒ Object

association table is queried by return value of this method. returns array of keys for parent record to match association record. if you want to skip association for particular record - return nil.



50
51
52
# File 'lib/active_record_custom_preloader/with_multiple_foreign_keys_loading.rb', line 50

def record_foreign_keys(parent_record)
  association_foreign_keys(parent_record)
end