带有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 行周围添加代码反引号。我只是在扫描代码时反复错过了这些信息——一旦我彻底阅读了它,我就抓住了错过的细节,它解决了我的问题。谢谢! 老实说,这是 ruby​​onrails.org 指南需要的完整示例。 视觉清晰度确实有很长的路要走,T.J.舒克。【参考方案2】:

在您的解决方案中使用 has_one 时的快速问题。 我将用户KandadaBoggu 给出的答案复制粘贴到this thread 中。


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 协会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嵌套表单:通过,如何编辑连接模型的属性?的主要内容,如果未能解决你的问题,请参考以下文章

Rails has_many:通过嵌套形式

如何处理 Rails 中的嵌套表单?

Rails has_many,如何实现嵌套关联?

Rails has_many :通过简单形式的嵌套形式

具有活动管理员的 Rails 双嵌套表单

Rails has_many 通过表单在连接模型中带有复选框和额外字段