Summary
Where City
has many Locations
(HABTM association), create a child record like this:
a = Location.create(:name=>'Site 1', :city => City.create(:name=>'A City'))
Issue: a.city_id
can't be changed in the database until a has been reloaded. Example:
a.city_id = 99
a.save # => true
a.city_id # => 11
Details
class City < ActiveRecord::Base
has_many :locations
end
class Location < ActiveRecord::Base
belongs_to :city
end
a = Location.create(:name=>'Site 1', :city => City.create(:name=>'A City'))
# Create a record manually for comparison
b = Location.create(:name=>a.name, :city_id=>a.city_id)
a.city_id = 99
a.save # => true
b.city_id = 99
b.save # => true
a.city_id # => 11
b.city_id # => 99
Both a
and b
appear identical on creation but behave differently. Al开发者_如何学Gothough a
is shown as valid after changing the city_id
, and is saved successfully, the city_id
is not changed.
However, if the record a
is reloaded before it is changed, the change "works":
a = Location.create(:name=>'Site 1', :city => City.create(:name=>'A City'))
a.reload
a.city_id = 99
a.save
a.city_id # => 99
This might seem rather arcane, since one can simply create the parent object first, but I discovered the issue using FactoryGirl,
factory :city do
name 'Jos'
end
factory :location do
name 'Site 1'
city { |a| a.association :city }
end
Factory(:location) shows the same behavior of having an unchangeable :city_id
until it's reloaded from the database. It took a long time before I figured out what was going on, why my tests were failing because of the change not happening as I expected.
I see from inspecting the new location
that it contains an entire city
object, while after the reload it does not, so that must be a clue, but what exactly is going on here? Would it be reasonable to expect FactoryGirl to automatically reload the object before returning, or would that break something? Of course I could do that with a callback, but I'm interested in simplicity.
(If you wonder why I don't just say location.city = new_city
rather than location.city_id = 99
, it's because I was writing a test and wanted to create "orphan" records with invalid references.)
精彩评论