レールで field_for を使用した動的チェックボックス
-
23-09-2019 - |
質問
リンク ボックスと多対多の関係があり、これらのモデルを 1 つのフォームにまとめて、同じページから更新できるようにしたいと考えています。check_box に配列のすべての要素を表示させるのに本当に苦労しています。ネットを調べて文字通り一日中これに取り組んできましたが、読んでいる情報を適用するのが難しいことがわかりました私の問題。また、私は RoR について非常に初心者で、少し古いビデオ チュートリアル (2.0 より前) に従っていたので、コードについて申し訳ありません。これまでのところ、配列内の 1 つのキー ペア (最後のキー ペア) だけを出力するようになりました。フォームの外にありますが、チュートリアルで使用されているコードは正しく動作します。それはほとんど役に立ちませんが!Host はメイン フォームの対象となるモデルで、Billing はフォームに追加しようとしている外部モデルです。
これは、チュートリアルのフォームの外で動作するコードです。
<% for billing in @billings -%>
<%= check_box_tag('billing_title[]', billing.id, @host.billings.collect
{|obj| obj.id}.include?(billing.id))%> <%= billing.title %><br />
<% end -%>
フォーム内でそれを機能させる方法を知る必要があるだけです。これは、配列キーペアをループした後に最後の配列キーペアのみを取得する前述のコードです。
<% f.fields_for :billings do |obj| %><br />
<%= check_box_tag('billing_title[]', billing.id, @billings.collect
{|obj| obj.id}.include?(billing.id))%> <%= billing.title %><br />
<% end %>
デバッグ(@billings):
---
- !ruby/object:Billing
attributes:
title: Every Month
id: "1"
attributes_cache: {}
- !ruby/object:Billing
attributes:
title: 12 Months
id: "2"
attributes_cache: {}
- !ruby/object:Billing
attributes:
title: 6 Months
id: "5"
attributes_cache: {}
ご協力をよろしくお願いいたします。
解決
Craig、あなたが探しているのは accepts_nested_attributes_for のようですね。これは、フォーム内でネストされたモデルを処理するより良い方法です。
Ryan の作品をすべて盗んでここに再投稿するのではなく、彼のスクリーンキャストへのリンクを載せておきます。
http://railscasts.com/episodes/196-nested-model-form-part-1
これは彼の複雑な形状シリーズに基づいています。
このチュートリアルを自分がやろうとしていることに合わせて調整できるはずですが、そうでない場合は喜んでお手伝いします。
編集:
コードを確認すると、問題の原因となっていることがいくつかあります。:)
まず第一に、関連付けを使用すると、請求のために追加のコレクションを取得する必要がありません。
@host = Host.find(params[:id])
@voips = Voip.find(:all)
@custsupps = Custsupp.find(:all)
@payments = Payment.find(:all)
@billings = Billing.find(:all) # <-- This is not needed and causing your problems
モデル内の関連付け設定により、これがすべて行われます。これは Rails の魔法の一部です。:D
ここで、関連付けを使用するときは、オブジェクトが実際に関連付けられていることを確認する必要があることに注意することが重要です。つまり、データベース内に 3 つの Billings オブジェクトがあり、それらが Host オブジェクトに関連付けられていない場合、それらはフォームに表示されません。
チェックボックスを使用して請求をホストに関連付けようとしている場合は、フォームには請求のみが表示されるため、別のアプローチをとる必要があります。 すでに関連付けられています ホストと一緒に。
ホストに関連付けられている既存の請求を編集または変更しようとしているだけの場合 (たとえば、チェックボックスが「有料」属性 (ブール値) を表している場合)、このアプローチは問題なく、フォーム コードは次のようになります。
<% f.fields_for :billings do |b| %><br />
<%= b.check_box :paid %> <%= b.title %>
<% end %>
したがって、機能の観点から何を達成しようとしているのかを明確にしていただければ、より良い解決策を見つけることができるでしょう。
他のヒント
私私の答えについてわからないんだけど、私はみます...
<% f.fields_for :billings, @billings do |obj| %>
# ...
<% end %>
私には見えます
あなたのコード例では、あなたが@billings
をループしている(請求額の配列は、あなたのコントローラから渡されたオブジェクト)、および現在の1のbilling
を呼び出します。
フォームのコードでは、(記号は請求額のActiveRecordをを参照):billings
をループして、現在の1 obj
を呼んでいます。その後、紛らわしい、あなたのコードの@ billings.collect機能に再び変数名obj
を再使用しています...しかし、これは地元のプライベートスコープを持っているし、あなたのメインループに影響を与えないが、目に解釈することは困難である必要があります。
obj
、それは変数billing
を使用していないため、とにかく、 - それはときにループを通過変え、それが持っていた最後の値を保持していない:最後の項目を以前のループから!あなただけの最後のタグを参照してください理由を説明します。 (また、debug(@billings)
機能は、種類のレコードを独自のループを行います - 。それは、ループを行うfields_forの内側ではありません)。
私はこのように、変数名billing
が再び再利用にフォームのコードの最初の行を変更することで始まります
<% f.fields_for :billings do |billing| %><br />
または、一体、いつでも - Rubyのブロック構文にはかなり最初は混乱することができます「コードを読んで再自分で書いていない - しかし、あなたはそれを基本的なコンポーネントへのすべてのダウンを破るとき、それは通常、単にアイテムのセットをループし、それぞれにいくつかの機能を実行います。また、同様の見栄え名の混同に注意:@billing、@billings、:請求額と請求額は、すべてのRubyとRailsのに異なるものです。幸運を!