1

私は本質的にこの投稿と同じ問題に遭遇していますが、状況は少し異なります: has_many ネストされたフォームと has_one ネストされたフォーム

しかし、他の誰かがその投稿で言及したように、提供された回答は問題を解決しません。

Invoice has_many items と各 Item has_one Modifier の関係が設定されています。私は単一の form_for Invoice を作成しようとしています。これを使用して、それぞれにモディファイアを使用して多くのアイテムを作成できます。

モデル

class Invoice < ActiveRecord::Base
  has_many :items
  has_many :modifiers, through: :items

  accepts_nested_attributes_for :items
end

class Item < ActiveRecord::Base
  belongs_to :invoice
  belongs_to :modifier

  accepts_nested_attributes_for :modifier
end

class Modifier < ActiveRecord::Base
  has_one :item
end

コントローラ

class Invoice
  def new
    @invoice = Invoice.new
  end

  def edit
  end

  ...
end

ビュー(haml)

invoice.html.haml:
= form_for @invoice do |f|
  = f.text_field :status

  = f.fields_for :items do |builder|
    = render partial: "items/fields", locals: { :f => builder }
  = link_to_add_association 'New Item', f, :items, partial: "items/fields", id: "add-item-button"

items/_fields.html.haml:
.nested-fields
  - @item = @invoice.items.build
  = f.fields_for :modifier, @item.build_modifier do |modifier|
    = modifier.text_field :name

何が起こっているのかを確認しましょう。ネストされた has_one 関係を構築するために、ネストされたフィールド パーシャルで Item を構築し、has_one Modifier を構築できるようにします。これは、Rails では、has_one 関係で「build_something」を明示的に呼び出す必要があるためです (通常、これはコントローラーの new で呼び出されますが、誰かが New Item ボタンをクリックした場合にのみビルドしたい)。新しい請求書を作成する場合、このコードは完全に機能します。コンソールを確認すると、関係が作成されていることがわかり、Modifier が正常に作成されたことを確認できます。

しかし、請求書の編集に戻ると、cocoon は私が既に修飾子を持っていることを認識しているため、パーシャルを 1 回呼び出して、単一の修飾子に必要な fields_ を作成します。これらのフィールドは空です。ただし、cocoon はその部分をレンダリングするため、新しい修飾子を使用して新しいコードを構築し、フィールドを空白に設定しているため、これは理にかなっています。モディファイヤを適切に保存したら、パーシャルに移動し、2 つのビルド呼び出しを削除して、保存されたモディファイヤ情報を適切に表示する編集ページを表示できるため、これが発生していることを確認できます。

もちろん、ビルド呼び出しを削除したので、フォームは私が作成した修飾子を保存しなくなりました。基本的に、新しい Modifier をビルドするにはビルド呼び出しが必要ですが、それらを表示したい場合はそこに置くことができません。

誰でもこの状況の解決策を持っていますか? 複数のスタック オーバーフローに関する質問を見つけましたが、いずれもこの問題を解決していません。

4

1 に答える 1

3

あなたは言いますhas_oneが、あなたのモデルではわかりhas_manyますか?

ネストされたパーシャルitems/_fieldsは間違っています。余分なアイテムを作成しますが、その必要はありません。Coccon は、link_to_add_association挿入する新しいアイテムをビルドします。

やりたいことをやるには2つの方法があります。

1) 部分的に

パーシャルで正しく処理するには、次のようにします ( items/_fields.html.haml) :

.nested-fields
  - f.object.build_modifier if f.object.new_record?  
  = f.fields_for :modifier do |modifier|
    = modifier.text_field :name 

レールでは、フォームのオブジェクトを参照するには を使用できますf.object。これは機能しますが、新しく作成されたオブジェクトかどうかを確認する必要があることに注意してください。または、 が存在するかどうかを確認することもできmodifierます。

2):wrap_objectオプションの使用 (ドキュメント)

Cocoon では、新しく作成されたオブジェクトで追加のコードを実行できます。したがって、あなたの場合は次のようになります。

= link_to_add_association('New item', f, :items,
        :wrap_object => Proc.new { |item| item.build_modifier; item })
于 2014-11-01T10:00:18.810 に答える