Rails has_many / acceptpts_nested_attributes_for Создать путаницу? - PullRequest
0 голосов
/ 05 июля 2018

Я немного сбит с толку, когда речь заходит об одном: создании в модели НЕСКОЛЬКИХ элементов модели "own_to".

В принципе, я видел это, где, скажем, у нас есть модель Person, и это Person has_many Addresses, а также accepts_nested_attributes_for :addresses

(Давайте представим, что Адрес - это просто одно текстовое поле, и, скажем, в форме мы получим 3 адреса на человека)

В «новом» контроллере я обычно вижу что-то вроде:

@person = Person.new
3.times { @person.addresses.build }

Затем в действии контроллера «создать» оно пройдет и выполнит обычное создание всех, принимая все 3 поля (используя fields_for форму) адресов. через что-то вроде:

def person_params
 params.require(:booking).permit(:name,:email,:age, :addresses_attributes => [:address])
end

И он прекрасно создаст все 3 адреса. Я не понимаю, как это работает. Строили 3 разных экземпляра, а потом как-то рельсы просто «знают», как их связать?

Может кто-нибудь объяснить, что происходит?

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

accept_nested_attributes_for :addresses в вашей модели Person определяет средство записи атрибутов для ассоциации has_many :addresses.

Теперь, когда вы отправляете свою форму в приложение Rails, параметры могут выглядеть примерно так:

"user"=>{"name"=>'John', "email"=>'john@domain.com',"age"=>"25"
addresses_attributes"=>{"0"=>{"address"=>"Street 1"}, "1"=>{"address"=>"Street 2"}, "2"=>{"address"=>"Street 2"}}}

Если вы внимательно посмотрите на параметр addresses_attributes, он будет похож на hash, и каждый key в этом hash представляет address объект. Именно так Rails точно узнает, что ему нужно создать 3 address записей.

Также, если вы хотите лучше понять это, просмотрите эту документацию по rails

Обновлен:

Не обязательно создавать экземпляры адресов заранее в действии new с 3.times { @person.addresses.build }

И жесткое кодирование количества адресов может быть неправильным способом сделать это. Что если кто-то захочет сохранить 5 адресов, а ваше приложение разрешит только 3?

Так что, вероятно, вы можете использовать Jquery и реализовать это намного лучше. Или даже вы можете использовать кокон драгоценный камень.

0 голосов
/ 05 июля 2018

Когда вы объявляете, что модель 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 количества адресов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...