Rails使用has_many嵌套表格:通过,如何编辑联接模型的属性?


103

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

我有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

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

@topic.articles.build

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

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

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


3
我正在尝试做与您相同的事情,只是在一个new / create动作中...我想知道您是否可以共享您的控制器动作。我想User通过Accounta Relationship作为一个linker... 创建a ,但我不知道新的内容和create动作的含义是什么...您介意吗?
穆罕默德

Answers:


90

找出答案。诀窍是:

@topic.linkers.build.build_article

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

然后以以下形式:

<%= 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...

13
让我知道这是否有帮助
Arcolye 2010年

13
Rails 3更新:如果您使用的是Rails 3,则form_for和field_for需要<%=%>而不是<%%>
Arcolye 2010年

我会在您添加的两行accepts_nested_attributes_for周围添加代码反引号。我只是在扫描代码时就反复错过了这些信息-仔细阅读后,我抓住了错过的细节,它解决了我的问题。谢谢!
TJ Schuck

2
老实说,这是rubyonrails.org指南所需要的完整示例。
ahnbizcad 2014年

TJ Schuck表示,视觉清晰度确实可以发挥很大作用。
ahnbizcad 2014年

6

当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."
        }
      }
    }
  }
}

注意linkers_attributes,实际上是如何HashString键零索引而不是键Array?好吧,这是因为发送到服务器的表单字段关键字如下所示:

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

现在,创建记录非常简单:

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

我不确定,但是我认为这一直都在假设accepts_nested_attributes_for
Arcolye

2
@Arcolye-当时在互联网上找到像这样的协会的信息真是太痛苦了-也许那天我的Google-fu休假了。当我作为同事时,我至少想在这里记录下来,我只是假设rails将linked_attributes转换为数组,而不是零索引哈希。希望这个消息能对将来的人有所帮助:)
Daniel Doezema

3

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


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

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

has_many关联的构建语法:

user.messages.build

has_one关联的构建语法:

user.build_profile  # this will work

user.profile.build  # this will throw error

阅读has_one协会文档以了解更多详细信息。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.