Когда вы объявляете, что модель Person accepts_nested_attributes_for :addresses
, все, что вы на самом деле говорите, это то, что я хочу, чтобы Rails создал методы экземпляра getter и setter на модели Person для адресов (множественное число).
Это похоже на другие отношения. Например, если вы объявите отношение has_many: friends в Person, вы сможете вызвать @person.friends
(получатель) или @person.friends.create
(установщик).
Вот визуальный ...
class Person < ActiveRecord::Base
# this is the getter method
def addresses
# I can retrieve all of the associated addresses for a particular person
end
# this is the setter method
def addresses_attributes=(attributes)
# I can take in any number of addresses and assoicate them to a particular person
end
end
Когда вы разрешаете address_attributes в контроллере
params.require(:person).permit(:addresses_attributes => [:address])
Думайте об этом, как будто вы разрешаете вызывать метод setter addresses_attribues
при создании Person ... метод set принимает адреса (множественное число), отправленные из формы, и связывает их с этим конкретным человеком. Но когда вы вызываете @ person.addresses, вы заметите, что он возвращает ActiveRecord :: Associations :: CollectionProxy , что важно понять.
В контроллере, когда вы говорите
@person = Person.new
3.times { @person.addresses.build }
Думайте об этом, как о создании пустой персоны и 3 пустых адресов, связанных с этой персоной, которые будут заполняться атрибутами только после вызова действия создания путем отправки формы.
EDIT:
Основным преимуществом вложенных атрибутов (и их отличия от обычной ассоциации) является то, что они позволяют использовать одну форму для создания / изменения родительского класса (в данном случае Person) и одновременно создавать / изменить связанные атрибуты (в данном случае адреса) с помощью fields_for
«Думаю, другая запутанная часть - как рельсы узнают, что у Человека есть 3 пустых адреса?»
Rails не знает сразу ... вот почему вы должны явно создать X количество пустых адресов в контроллере. Так что теперь, когда вы вызываете form.fields_for :addresses
, остается только X объема памяти для хранения X количества адресов.