简体   繁体   English

Rails has_many / accepts_nested_attributes_for造成混乱吗?

[英]Rails has_many/accepts_nested_attributes_for Create confusion?

I'm a bit confused when it comes to one thing and that's creating MULTIPLE "belongs_to" model items in the controller. 当涉及到一件事时,我有点困惑,那就是在控制器中创建多个“ belongs_to”模型项。

Basically, I've seen it where say we have a Person model, and that Person has_many Addresses and also accepts_nested_attributes_for :addresses 基本上,我在说我们有一个Person模型的地方看到过它,并且Person has_many Addresses并且accepts_nested_attributes_for :addresses

(Let's pretend the Address is just a single text field, and let's say in the form we are going to end up having 3 addresses for a person) (让我们假装“地址”只是一个文本字段,以表单的形式,我们最终将为一个人拥有3个地址)

In the "new" controller I will typically see something like: 在“新”控制器中,我通常会看到类似以下内容的内容:

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

Then in the "create" controller action it'll go through and do the normal create all while accepting all 3 fields (using fields_for form) of addresses. 然后,在“创建”控制器操作中,将接受所有3个地址字段(使用fields_for形式),然后进行正常的全部创建。 via something like: 通过类似的东西:

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

And it'll create all 3 addresses just fine. 它将创建所有3个地址。 I don't understand how it works. 我不明白它是如何工作的。 Were building 3 different instances and then somehow rails just "knows" how to associate them? 正在构建3个不同的实例,然后以某种方式Rails只是“知道”如何将它们关联起来?

Can anyone explain what's going on? 谁能解释这是怎么回事?

When you declare that a Person model accepts_nested_attributes_for :addresses , all you are really saying is I want Rails to create getter and setter instance methods on the Person model for addresses (plural). 当您声明一个Person模型accepts_nested_attributes_for :addresses ,您真正要说的是我希望Rails在Person模型上为地址(复数)创建getter和setter实例方法。 This is similar to other relationships. 这类似于其他关系。 For instance, if you declare a has_many :friends relationship on Person, you would be able to call @person.friends (the getter) or @person.friends.create (the setter). 例如,如果您在Person上声明has_many:friends关系,则可以调用@person.friends (获取程序)或@person.friends.create (设置程序)。 Heres a visual... 这是视觉效果...

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

When you permit addresses_attributes in the controller 当您允许在控制器中使用addresses_attributes时

params.require(:person).permit(:addresses_attributes => [:address])

Think of it like you are allowing the addresses_attribues setter method to be called when creating a Person...the setter method takes in the addresses (plural) submitted from the form and associates them with that particular person. 想想这就像你让addresses_attribues setter方法创建一个人的时候,被称为... setter方法接受来自表单提交的地址(复数),并将它们与特定的人相关联。 But, when you call @person.addresses, you'll notice that it returns an ActiveRecord::Associations::CollectionProxy , which is important to understand. 但是,当您调用@ person.addresses时,您会注意到它返回一个ActiveRecord :: Associations :: CollectionProxy ,这对理解很重要。

In the controller, when you say 在控制器中,当您说

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

Think of it like creating an empty Person and 3 empty addresses associated with that person, which will only be populated with attributes once the create action is called by submitting the form. 可以将其想象为创建一个空的Person以及与该Person关联的3个空地址,只有在通过提交表单调用create动作后,这些属性才会填充属性。

EDIT: 编辑:

The main benefit of nested attributes (and it's difference from a normal association) is that it allows you to use a single form to create/modify the parent class (in this case, the Person), and at the same time create/modify it's associated attributes (in this case, addresses) through the use of fields_for 嵌套属性的主要优点(与常规关联有所不同)是,它允许您使用一种形式来创建/修改父类(在本例中为Person),同时创建/修改父类。通过使用fields_for关联属性(在本例中为地址)

"I guess the other confusing part is how rails knows that the Person has 3 empty addresses?" “我想另一个令人困惑的部分是,rails如何知道此人有3个空地址?”

Rails doesn't know right off the bat...which is why you have to explicitly instantiate X amount of empty addresses in the controller. Rails马上就不知道了。这就是为什么您必须在控制器中显式实例化X个空地址的原因。 So now when you call form.fields_for :addresses there is only X amount of memory to store X amount of addresses. 因此,现在当您调用form.fields_for :addresses ,只有X数量的内存可以存储X数量的地址。

accept_nested_attributes_for :addresses in your Person model defines an attributes writer for the has_many :addresses association. Person模型中的accept_nested_attributes_for :addresses定义了has_many :addresses关联的属性accept_nested_attributes_for :addresses

Now when you submit your form to the Rails application, The params might look something similar to this: 现在,当您将表单提交到Rails应用程序时,参数可能看起来类似于以下内容:

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

If you take a close look at the addresses_attributes param, it looks similar to a hash and each key in that hash represents an address object. 如果你把在密切关注addresses_attributes PARAM,它类似于一个hash和每个keyhash表示address的对象。 That is how Rails will exactly know that it has to create 3 address records. 这就是Rails确切知道必须创建3条address记录的方式。

Also if you would like to understand this better, go through this rails documentation 另外,如果您想更好地理解这一点,请阅读此Rails文档

Updated: 更新:

It is not at all compulsory to instantiate the addresses in advance in the new action with 3.times { @person.addresses.build } new动作中使用3.times { @person.addresses.build }预先实例化地址完全不是强制性的。

And hardcoding number of addresses might not be a right way to do it. 硬编码地址可能不是正确的方法。 What if someone wants to store 5 addresses and your application allows just 3? 如果有人要存储5个地址而您的应用程序只允许3个地址怎么办?

So probably you can use Jquery and implement this in a much better way. 因此,您可能可以使用Jquery并以更好的方式实现它。 Or even you could use cocoon gem. 或者甚至可以使用宝石。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Rails,accepts_nested_attributes_for has_many:通过构建 - Rails, accepts_nested_attributes_for has_many: through with build Rails 3具有has_many的accepts_nested_attributes_for:through关系 - Rails 3 accepts_nested_attributes_for with has_many :through relationships accepted_nested_attributes_for with has_many =&gt;:通过选项 - accepts_nested_attributes_for with has_many => :through Options has_many accepts_nested_attributes_for关联问题 - has_many accepts_nested_attributes_for association question accepted_nested_attributes_for with has_many polymorphic - accepts_nested_attributes_for with has_many polymorphic has_many:through和accepts_nested_attributes_用于复制记录 - has_many :through and accepts_nested_attributes_for duplicating records Rails accepts_nested_attributes_for通过以下方式不保存has_many上的关联 - Rails accepts_nested_attributes_for not saving association on has_many through Rails 4通过关系通过has_many接受hass_nested_attributes_for::_destroy无法正常工作 - Rails 4 accepts_nested_attributes_for for has_many through relationship: :_destroy is not working Rails bug:accepts_nested_attributes_for没有更新我的has_many关联 - Rails bug: accepts_nested_attributes_for is not updating my has_many association Rails 6 使用 has_many 关系和 accepts_nested_attributes_for 连接表 - Rails 6 Joins Tables using has_many relationships and accepts_nested_attributes_for
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM