Ответ 1
Я решил эту проблему, добавив опцию update_only
:
accepts_nested_attributes_for :profile, update_only: true
Теперь новый профиль создается только в том случае, если он еще не существует.
У меня есть пользовательский и вложенный класс профиля следующим образом:
class User < ActiveRecord::Base
has_one :profile
attr_accessible :profile_attributes
accepts_nested_attributes_for :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
attr_accessible :name
end
user = User.find(1)
user.profile.id # => 1
user.update_attributes(profile_attributes: {name: 'some name'})
user.profile.id # => 2
Я не понимаю, почему рельсы выбрасывают старый профиль и создают новый.
Использование
user.profile.update_attributes({name: 'some name'})
просто обновляет текущий профиль, как ожидалось. Но в этом случае я не использую accepts_nested_attributes_for
Кто-нибудь знает, почему обновление происходит таким образом? Я бы предпочел не создавать базу данных строк профиля, не связанных с каким-либо пользователем.
Я решил эту проблему, добавив опцию update_only
:
accepts_nested_attributes_for :profile, update_only: true
Теперь новый профиль создается только в том случае, если он еще не существует.
Для всех, у кого такая же проблема в Rails 4: fields_for уже добавляет идентификатор для ваших вложенных форм, но вы должны разрешить параметр id. Мне разрешен только параметр: object_name_id, и поскольку это не вызывает никаких ошибок, мне потребовалось некоторое время, пока я не увидел это в журналах сервера. Надеюсь, это поможет кому-то тратить меньше времени на меня:)
Если вы проверите свою форму, вам нужно установить атрибут id в хэш-вложенном атрибуте для вашего объекта Profile. Если идентификатор не установлен, ActiveRecord принимает новый объект.
Например, если у вас была форма ERB, создающая набор параметров пользователя с вложенным параметром hash для профиля вложенного профиля внутри пользователя, вы можете включить скрытое значение для идентификатора профиля, например:
<%= hidden_field "user[profile_attributes][id]", @profile.id %>
Я был поражен этим в другой версии Rails, и я думал, что потеряю рассудок. Добавляя update_only = > true, я решил, что это ошибка в Rails.
Симптомы в моем случае: я бы получил ассоциацию с элементом sort_to deleted и новым вложенным объектом - до тех пор, пока я не обновил страницу. После этого он работал правильно.
В моем случае я добавил метод before_save в свой вложенный класс и распечатал его. Я также распечатал атрибуты перед вызовом update_attributes. Они правильно установили "parent_id" . Я также включил скрытое поле id в форме, без изменений - это было нормально, поскольку оно уже было включено с помощью fields_for...
Сюрприз: я видел один звонок для обновления, генерирующий два вызова сохранения. Первое сохранение имеет идентификатор вложенного объекта, но null для идентификатора belongs_to. - поэтому это приведет к обновлению записи, чтобы установить "parent_id" в значение null. Во втором сохранении будет установлен параметр "parent_id" , но у него будет установлен идентификатор вложенного объекта.
Как я уже сказал, я исправил его, добавив update_only = > true, но я думаю, что это все еще ошибка.
Я хотел бы узнать, применяются ли вышеуказанные симптомы к вашему делу, чтобы подтвердить, что это ошибка.