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値を持ちます。出てきますか?
答えを見つけました。トリックは:
@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によって生成されたフォームが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
は実際には、インデックスがゼロのHash
であり、String
キーではなく、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
ソリューションでhas_oneを使用する場合の簡単なGOTCHA。ユーザー KandadaBogg in 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
アソシエーション ドキュメント をお読みください。