insert with existing association does not seem to work
jwoodrow opened this issue ยท 0 comments
Hi ๐
I'm trying to insert multiple new records with a has_many
association but it seems like it's not working correctly in this case
class Vehicle < ActiveRecord::Base
has_many :drivers
end
class Driver < ActiveRecord::Base
belongs_to :vehicle
end
driver = Driver.create
vehicle = Vehicle.new(drivers: [driver])
Vehicle.import([vehicle], recursive: true, on_duplicate_key_update: :all)
driver.reload.vehicle_id #=> nil
when digging a bit I found that here although models.first.id
is set correctly, models.first.association(:drivers).target.first.vehicle.id
is nil
like its a copy. so since vehicle_id
, the foreign key is not set then changed?
returns false
Shouldn't this foreign key assignment be done before, so if the only change is the belongs_to association it still detects a change ?
changing
activerecord-import/lib/activerecord-import/import.rb
Lines 977 to 1009 in e3331d5
def find_associated_objects_for_import(associated_objects_by_class, model)
associated_objects_by_class[model.class.name] ||= {}
return associated_objects_by_class unless model.id
association_reflections =
model.class.reflect_on_all_associations(:has_one) +
model.class.reflect_on_all_associations(:has_many)
association_reflections.each do |association_reflection|
associated_objects_by_class[model.class.name][association_reflection.name] ||= []
association = model.association(association_reflection.name)
association.loaded!
# Wrap target in an array if not already
association = Array(association.target)
# This line is added
association.each { |child| child.public_send("#{association_reflection.foreign_key}=", model.id) }
changed_objects = association.select { |a| a.new_record? || a.changed? }
changed_objects.each do |child|
# Removed the foreign_key assignment here
# For polymorphic associations
association_name = if model.class.respond_to?(:polymorphic_name)
model.class.polymorphic_name
else
model.class.base_class
end
association_reflection.type.try do |type|
child.public_send("#{type}=", association_name)
end
end
associated_objects_by_class[model.class.name][association_reflection.name].concat changed_objects
end
associated_objects_by_class
end
Current workaround is also to add driver.send(:mutations_from_database).force_change('vehicle_id')
right after assigning the new vehicle
to the existing driver
. The fact that mutations_from_database
is a private method is kind of an indicator that this is not really what it's made for