带有has_many的Rails嵌套表单:通过,如何编辑连接模型的属性?
Posted
技术标签:
【中文标题】带有has_many的Rails嵌套表单:通过,如何编辑连接模型的属性?【英文标题】:Rails nested form with has_many :through, how to edit attributes of join model? 【发布时间】:2011-01-12 01:13:11 【问题描述】:在使用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
...并在topics/new.html.erb中制作嵌套表格...
<% form_for(@topic) do |topic_form| %>
...fields...
<% topic_form.fields_for :articles do |article_form| %>
...fields...
...Rails 会自动创建链接器,这很棒。 现在我的问题是:我的链接器模型还具有我希望能够通过“新主题”表单更改的属性。但是 Rails 自动创建的链接器除了 topic_id 和 article_id 之外的所有属性都具有 nil 值。如何将其他链接器属性的字段放入“新主题”表单中,以免它们出现为零?
【问题讨论】:
我正在尝试做和你一样的事情,只是在一个新的/创建动作中......我想知道你是否可以分享你的控制器动作。我想通过Account
使用Relationship
作为linker
创建一个User
...但我无法弄清楚 new 和 create 操作的含义是什么...你介意吗?
robots.thoughtbot.com/…
【参考方案1】:
想出了答案。诀窍是:
@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...
【讨论】:
如果有帮助请告诉我 Rails 3 更新:如果您使用的是 Rails 3,form_for 和 field_for 需要 而不是 。 我会在您添加的两个 accept_nested_attributes_for 行周围添加代码反引号。我只是在扫描代码时反复错过了这些信息——一旦我彻底阅读了它,我就抓住了错过的细节,它解决了我的问题。谢谢! 老实说,这是 rubyonrails.org 指南需要的完整示例。 视觉清晰度确实有很长的路要走,T.J.舒克。【参考方案2】:在您的解决方案中使用 has_one 时的快速问题。 我将用户KandadaBoggu 给出的答案复制粘贴到this thread 中。
build
方法签名对于 has_one
和 has_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
协会documentation 了解更多详情。
【讨论】:
【参考方案3】:当 Rails 生成的表单提交到 Rails controller#action
时,params
将具有类似这样的结构(添加了一些组成的属性):
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]
现在创建记录很简单:
TopicController < ApplicationController
def create
@topic = Topic.create!(params[:topic])
end
end
【讨论】:
我不确定,但我认为这一直是与accepts_nested_attributes_for
一起假设的
@Arcolye - 在互联网上为这样的协会查找此信息当时非常痛苦 - 也许那天我的 google-fu 关闭了。我想至少在这里记录它,因为我作为我的同事,我只是假设 rails 将linked_attributes 转换为数组,而不是零索引哈希。希望这个花絮可以帮助将来的人:)以上是关于带有has_many的Rails嵌套表单:通过,如何编辑连接模型的属性?的主要内容,如果未能解决你的问题,请参考以下文章