lib/torque/postgresql/associations/preloader/association.rb in torque-postgresql-2.4.5 vs lib/torque/postgresql/associations/preloader/association.rb in torque-postgresql-3.0.0
- old
+ new
@@ -9,14 +9,67 @@
delegate :connected_through_array?, to: :@reflection
# For reflections connected through an array, make sure to properly
# decuple the list of ids and set them as associated with the owner
def run
+ return self if run?
return super unless connected_through_array?
+
+ @run = true
send("run_array_for_#{@reflection.macro}")
+ self
end
+ # Correctly correlate records when they are connected theough an array
+ def set_inverse(record)
+ return super unless connected_through_array? && @reflection.macro == :has_many
+
+ # Only the first owner is associated following the same instruction
+ # on the original implementation
+ convert_key(record[association_key_name])&.each do |key|
+ if owners = owners_by_key[key]
+ association = owners.first.association(reflection.name)
+ association.set_inverse_instance(record)
+ end
+ end
+ end
+
+ # Requires a slight change when running on has many since the value
+ # of the foreign key being an array
+ def load_records(raw_records = nil)
+ return super unless connected_through_array? && @reflection.macro == :has_many
+
+ @records_by_owner = {}.compare_by_identity
+ raw_records ||= loader_query.records_for([self])
+
+ @preloaded_records = raw_records.select do |record|
+ assignments = false
+
+ keys = convert_key(record[association_key_name]) || []
+ owners_by_key.values_at(*keys).each do |owner|
+ entries = (@records_by_owner[owner] ||= [])
+
+ if reflection.collection? || entries.empty?
+ entries << record
+ assignments = true
+ end
+ end
+
+ assignments
+ end
+ end
+
+ # Make sure to change the process when connected through an array
+ def owners_by_key
+ return super unless connected_through_array?
+ @owners_by_key ||= owners.each_with_object({}) do |owner, result|
+ Array.wrap(convert_key(owner[owner_key_name])).each do |key|
+ (result[key] ||= []) << owner
+ end
+ end
+ end
+
private
# Specific run for belongs_many association
def run_array_for_belongs_to_many
# Add reverse to has_many
@@ -36,35 +89,9 @@
end
records.default_proc = nil
owners.each do |owner|
associate_records_to_owner(owner, records[owner[owner_key_name]] || [])
- end
- end
-
- if PostgreSQL::AR604
- # This is how Rails 6.0.4 and 6.1 now load the records
- def load_records
- return super unless connected_through_array?
-
- @records_by_owner = {}.compare_by_identity
- raw_records = owner_keys.empty? ? [] : records_for(owner_keys)
-
- @preloaded_records = raw_records.select do |record|
- assignments = false
-
- ids = convert_key(record[association_key_name])
- owners_by_key.values_at(*ids).flat_map do |owner|
- entries = (@records_by_owner[owner] ||= [])
-
- if reflection.collection? || entries.empty?
- entries << record
- assignments = true
- end
- end
-
- assignments
- end
end
end
# Build correctly the constraint condition in order to get the
# associated ids