Вложенный атрибут update_attributes использует вставку, а не обновление - PullRequest
28 голосов
/ 30 марта 2012

У меня есть класс пользователя и вложенного профиля:

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

Я не понимаю, почему rails выбрасывает старый профиль и создает новый.

Использование

user.profile.update_attributes({name: 'some name'})

просто обновляет текущий профиль, как и ожидалось.Но в этом случае я не пользуюсь accepts_nested_attributes_for

Кто-нибудь знает, почему обновление происходит таким образом?Я бы предпочел не заканчивать с базой данных строк профиля, не связанных ни с одним пользователем.

Ответы [ 4 ]

36 голосов
/ 02 ноября 2013

Для всех, у кого такая же проблема в Rails 4: fields_for уже добавляет id для ваших вложенных форм, но вы должны разрешить параметр: id. Я разрешил только параметр: object_name_id, и поскольку он не выдает никаких ошибок, мне потребовалось некоторое время, пока я не увидел это в журналах сервера. Надеюсь, это поможет кому-то тратить на это меньше времени:)

23 голосов
/ 30 марта 2012

Если вы проверяете свою форму, вам нужно установить атрибут id в хэше вложенного атрибута для вашего объекта Profile.Если идентификатор не установлен, ActiveRecord предполагает, что это новый объект.

Например, если у вас была форма ERB, создающая набор параметров 'user' с вложенным хешем параметра profile_attributes для вложенного профиля впользователь, вы можете включить скрытое значение для идентификатора профиля, например:

<%= hidden_field "user[profile_attributes][id]", @profile.id %>
19 голосов
/ 04 апреля 2012

Я решил эту проблему, добавив параметр update_only:

accepts_nested_attributes_for :profile, update_only: true

Теперь новый профиль создается, только если он еще не существует.

0 голосов
/ 01 марта 2016

Меня поразило это в другой версии Rails, и я думал, что сойду с ума.Хотя добавление update_only => true решило это, я думаю, что это ошибка где-то в Rails.

Симптомы в моем случае: я получал бы связь с удаленным bound_to и созданным новым вложенным объектом - пока я сначала не обновлю страницу,После этого он работал правильно.

В моем случае я добавил метод before_save во вложенный класс и распечатал то, что сохранил.Я также напечатал атрибуты перед вызовом update_attributes.У них "parent_id" установлен правильно.Я также включил скрытое поле идентификатора в форму, без изменений - что было нормально, поскольку оно уже было включено с помощью fields_for ...

Сюрприз: я видел один вызов обновления, генерирующий два вызова сохранения.При первом сохранении идентификатор вложенного объекта будет иметь значение NULL для идентификатора assign_to.- так что это обновит запись, чтобы установить "parent_id" в ноль.Во втором сохранении будет установлен «parent_id», но для идентификатора вложенного объекта будет установлено значение «ноль».

Как я уже сказал, я исправил это, добавив update_only => true, но я думаю, что это все еще ошибка.

Я хотел бы выяснить, относятся ли вышеуказанные симптомы к вашему случаю, чтобы подтвердить, что это ошибка.

...