has_many:throughを使用したRailsのネストされたフォーム、結合モデルの属性を編集する方法は?


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

...そして、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値を持っています。他のリンカー属性のフィールドを「新しいトピック」フォームに入れて、それらがnilにならないようにするにはどうすればよいですか?


3
私はあなたと同じことをしようとしていますが、新規/作成アクションでのみ...コントローラのアクションを共有できるかどうか疑問に思っています。私が作成したいUserを通じてAccount使用しRelationshiplinker...しかし、私は新しい何かを把握し、アクションはのような...あなたが気になり見に意図されて作成することはできませんか?
モハマド

回答:


90

答えを見つけ出した。トリックは:

@topic.linkers.build.build_article

これでリンカーが構築され、次に各リンカーの記事が構築されます。したがって、モデルでは:
topic.rbにはaccepts_nested_attributes_for :linkers
リンカーが必要です。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

13
3更新がレール:のform_forとfield_for必要<%=%>の代わりに<%%>のあなたがRailsの3を使用している場合
Arcolye

追加した2つのaccepts_nested_attributes_for行の周りにコードバックティックを追加します。コードをスキャンするだけで何度もその情報を見逃しました-完全に読んだ後、その見落とした詳細を見つけて問題を解決しました。ありがとう!
TJ Schuck

2
正直なところ、これはrubyonrails.orgガイドが必要とする完全な例です。
ahnbizcad 14

TJ Schuckさん、視覚的な明快さは本当に長い道のりです。
ahnbizcad 14

6

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られていることに注意してください。これは、サーバーに送信されるフォームフィールドキーが次のようになるためです。StringArray

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 2013年

2
@Arcolye-このような協会のインターネットでこの情報を見つけるのは、当時はとても大変でした-おそらく私のgoogle-fuはその日休みでした。私は同僚として私が少なくともここに文書化したかったので、レールがゼロのインデックス付きハッシュではなく、linked_attributesを配列に変換したと想定しました。うまくいけば、この一口が将来の誰かを助けるでしょう:)
Daniel Doezema '17年

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関連ドキュメントをご覧ください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.