Rails的嵌套窗体has_many:通过,如何编辑连接模型的属性?

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

我有3个模型:由连接器join的主题和文章

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 

所以,当我在主题控制器的“新”动作中构build文章…

 @topic.articles.build 

…并在主题/ new.html.erb中嵌套的forms…

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

… Rails自动创build链接器,这是伟大的。 现在对于我的问题:我的链接器模型也有属性,我希望能够通过“新主题”forms进行更改。 但是Rails自动创build的链接器对于除了topic_id和article_id之外的所有属性都具有nil值。 我怎样才能把字段的其他链接器属性到“新主题”forms,所以他们不出来零?

找出答案。 诀窍是:

 @topic.linkers.build.build_article 

构build连接器,然后为每个链接器构build文章。 所以,在模型中:
topic.rb需要accept_nested_attributes_for accepts_nested_attributes_for :linkers
linker.rb需要accept_nested_attributes_for 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... 

当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实际上是一个零索引的使用String键的Hash ,而不是一个Array ? 那么,这是因为发送到服务器的表单字段键如下所示:

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

创buildlogging现在简单如下:

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

在解决scheme中使用has_one时的快速GOTCHA。 我只是复制粘贴用户KandadaBoggu在这个线程给出的答案。


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

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

has_many关联的构build语法:

 user.messages.build 

has_one关联的构build语法:

 user.build_profile # this will work user.profile.build # this will throw error 

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