Сводка
Если City
имеет много Locations
(ассоциация HABTM), создайте дочернюю запись, например:
a = Location.create(:name=>'Site 1', :city => City.create(:name=>'A City'))
Проблема: a.city_id
нельзя изменить в базе данных, пока не будет перезагружен файл.Пример:
a.city_id = 99
a.save # => true
a.city_id # => 11
Подробности
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
И a
, и b
выглядят одинаково при создании, но ведут себя по-разному.Хотя a
отображается как действительное после изменения city_id
и успешно сохраняется, city_id
не изменяется.
Однако, если запись a
перезагружается до ее изменения,изменить «работает»:
a = Location.create(:name=>'Site 1', :city => City.create(:name=>'A City'))
a.reload
a.city_id = 99
a.save
a.city_id # => 99
Это может показаться довольно загадочным, поскольку сначала можно просто создать родительский объект, но я обнаружил проблему с помощью FactoryGirl,
factory :city do
name 'Jos'
end
factory :location do
name 'Site 1'
city { |a| a.association :city }
end
Factory (:location) показывает то же поведение с неизменным :city_id
, пока он не будет перезагружен из базы данных.Прошло много времени, прежде чем я понял, что происходит, почему мои тесты провалились из-за того, что изменения не произошли, как я ожидал.
Из проверки нового location
я вижу, что он содержит целый объект city
, а после перезагрузки его нет, так что это должно быть ключом, но что именно здесь происходит?Разумно ли ожидать, что FactoryGirl автоматически перезагрузит объект перед возвратом, или это что-то сломает?Конечно, я мог бы сделать это с помощью обратного вызова, но меня интересует простота.
(Если вам интересно, почему я просто не говорю location.city = new_city
, а не location.city_id = 99
, это потому, что я писал тест и хотел создать «бесхозные» записи с недействительными ссылками.)