Rails 4 и изменение поведения при связывании существующих вложенных моделей - PullRequest
0 голосов
/ 09 января 2019

Я обновляю с 3,2 до 4,0. Я заметил, что при использовании ActiveRecord произошли большие изменения в поведении существующей дочерней модели с новой родительской моделью.

Обратите внимание на следующее:

class Parent
  has_many :kids
  accepts_nested_attributes_for :kids
end

class Kid
  belongs_to :parent
end

и следующий контекст:

Kid {id: 1, name: 'kid1', parent_id: nil}
Kid {id: 2, name: 'kid2', parent_id: nil}

Если я отправлю эти параметры на контроллер:

"parent"=>{ "title"=>"mom", "kids_attributes"=>{ "1"=>{"id"=>"1", "name"=> "kiddo"}, "2"=>{"id"=>"2"} }

И сделать:

p = Parent.new(params[:parent])
p.save

С Rails 3.2 результат:

Parent {id: 1, title: 'mom'}
Kid {id: 1, name: 'kiddo', parent_id: 1}
Kid {id: 2, name: 'kid2', parent_id: 1}

Но в Rails 4.0 (после преобразования в strong_parameters) вызов Parent.new вызывает ошибку

Couldn't find Kid with ID=1 for Parent with ID=

читаю эту ветку

Кажется, теперь мне нужно сначала создать Родителя, а затем спасти детей.

Это проблема в тех случаях, когда у меня могут быть существующие и несуществующие дети, поданные одновременно. Я должен был бы вручную проверить, какие дочерние элементы уже существуют (есть и идентификатор), удалить их из параметров, сохранить родительский элемент, а затем обновить их атрибуты?

Это то, что я должен сделать, чтобы обновить Rails, или есть что-то еще, вызывающее такое другое поведение?

На самом деле, когда я делаю

@parent = Parent.new
@parent.kids.build(parent_parameters[:kids_attributes])

ActiveRecord не выполняет поиск, и дети остаются только с установленным идентификатором. В моем контексте я пока не могу сохранить ни одну из записей.

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Я прочитал эту [тему] [2]

Итак, теперь, если вам нужно связать существующую запись, вы должны отправить атрибуты следующим образом:

"parent"=>{ "title"=>"mom", "kid_ids"=> ["1", "2"] }

А если вам нужно создать / обновить новые / связанные записи, вы отправляете атрибуты обычным образом:

"parent"=>{ "title"=>"mom", "kids_attributes"=>{ "1"=>{"name"=> "kiddo"}, "2"=>{"id"=>"1","name"=>"boy"} }

Чтобы сделать первое, я должен был использовать это в форме

<%= check_box_tag "parent[kid_ids][]", parent.kids.include?(kid) %>

И принять эти параметры

params.require(:parent).permit( { :kid_ids => [] } )

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

0 голосов
/ 09 января 2019

Короче говоря:

  1. Передавать только атрибуты id для обновления дочернего элемента
  2. И никогда не передавайте атрибуты id при создании нового потомка

Например, если вы хотите обновить kid1 и создать нового потомка с именем kid2, отправьте параметры в контроллер, например:

"parent"=>{ "title"=>"mom", "kids_attributes"=>{ "1"=>{"id"=>"1", "name"=> "kiddo"}, "2"=>{"name"=>"kid2"} }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...