Ruby-on-rails 带有 has_many 的 Rails 嵌套表单:通过,如何编辑连接模型的属性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2182428/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 22:13:51  来源:igfitidea点击:

Rails nested form with has_many :through, how to edit attributes of join model?

ruby-on-railsjoinnestednested-forms

提问by Arcolye

How do you edit the attributes of a join model when using accepts_nested_attributes_for?

使用 accepts_nested_attributes_for 时如何编辑连接模型的属性?

I have 3 models: Topics and Articles joined by Linkers

我有 3 个模型:链接器加入的主题和文章

class Topic < ActiveRecord::Base
  has_many :linkers
  has_many :articles, :through => :linkers, :foreign_key => :article_id
  accepts_nested_attributes_for :articles
end
class Article < ActiveRecord::Base
  has_many :linkers
  has_many :topics, :through => :linkers, :foreign_key => :topic_id
end
class Linker < ActiveRecord::Base
  #this is the join model, has extra attributes like "relevance"
  belongs_to :topic
  belongs_to :article
end

So when I build the article in the "new" action of the topics controller...

因此,当我在主题控制器的“新”操作中构建文章时...

@topic.articles.build

...and make the nested form in topics/new.html.erb...

...并在topics/new.html.erb 中创建嵌套表单...

<% form_for(@topic) do |topic_form| %>
  ...fields...
  <% topic_form.fields_for :articles do |article_form| %>
    ...fields...

...Rails automatically creates the linker, which is great. Now for my question:My Linker model also has attributes that I want to be able to change via the "new topic" form. But the linker that Rails automatically creates has nil values for all its attributes except topic_id and article_id. How can I put fields for those other linker attributes into the "new topic" form so they don't come out nil?

...Rails 会自动创建链接器,这很棒。 现在问我的问题:我的链接器模型也有我希望能够通过“新主题”表单更改的属性。但是 Rails 自动创建的链接器的除 topic_id 和 article_id 之外的所有属性都为 nil 值。如何将那些其他链接器属性的字段放入“新主题”表单中,以便它们不会出现为零?

采纳答案by Arcolye

Figured out the answer. The trick was:

想通了答案。诀窍是:

@topic.linkers.build.build_article

That builds the linkers, then builds the article for each linker. So, in the models:
topic.rb needs accepts_nested_attributes_for :linkers
linker.rb needs accepts_nested_attributes_for :article

这将构建链接器,然后为每个链接器构建文章。因此,在模型中:
topic.rb 需要accepts_nested_attributes_for :linkers
linker.rb 需要accepts_nested_attributes_for :article

Then in the form:

然后在表格中:

<%= form_for(@topic) do |topic_form| %>
  ...fields...
  <%= topic_form.fields_for :linkers do |linker_form| %>
    ...linker fields...
    <%= linker_form.fields_for :article do |article_form| %>
      ...article fields...

回答by Daniel Doezema

When the form generated by Rails is submitted to the Rails controller#action, the paramswill have a structure similar to this (some made up attributes added):

当 Rails 生成的表单提交到 Rails 时controller#actionparams会有类似的结构(添加了一些组合属性):

params = {
  "topic" => {
    "name"                => "Ruby on Rails' Nested Attributes",
    "linkers_attributes"  => {
      "0" => {
        "is_active"           => false,
        "article_attributes"  => {
          "title"       => "Deeply Nested Attributes",
          "description" => "How Ruby on Rails implements nested attributes."
        }
      }
    }
  }
}

Notice how linkers_attributesis actually a zero-indexed Hashwith Stringkeys, and not an Array? Well, this is because the form field keys that are sent to the server look like this:

请注意linkers_attributes实际上如何Hash使用String键进行零索引,而不是Array? 嗯,这是因为发送到服务器的表单字段键看起来像这样:

topic[name]
topic[linkers_attributes][0][is_active]
topic[linkers_attributes][0][article_attributes][title]

Creating the record is now as simple as:

创建记录现在非常简单:

TopicController < ApplicationController
  def create
    @topic = Topic.create!(params[:topic])
  end
end

回答by 8bithero

A quick GOTCHA for when using has_one in your solution. I will just copy paste the answer given by user KandadaBogguin this thread.

在您的解决方案中使用 has_one 时的快速 GOTCHA。我将复制粘贴用户KandadaBoggu此线程中给出的答案。



The buildmethod signature is different for has_oneand has_manyassociations.

和关联的build方法签名不同 。has_onehas_many

class User < ActiveRecord::Base
  has_one :profile
  has_many :messages
end

The build syntax for has_manyassociation:

has_many关联的构建语法:

user.messages.build

The build syntax for has_oneassociation:

has_one关联的构建语法:

user.build_profile  # this will work

user.profile.build  # this will throw error

Read the has_oneassociation documentationfor more details.

阅读has_one关联文档以获取更多详细信息。