Rails アプリケーションでネストされたフォーム ( RailsCast #196 ) を使用しています。これが私の現在の問題と私がやりたいことです。ただし、この問題に取り組むための最善の方法がわからないので、いくつかの指針を得たいと思っています。
次のフィールドのいくつかを含むdish
フォーム ( ) があります。_form.html.haml
.control-group
=f.label :menu, :class => 'control-label'
.controls
=select("dish", "menu_id", (current_user.has_role? :admin) ? (Menu.all.collect {|m| [ m.name, m.id ] }) : (current_user.menus.all.collect {|m| [ m.name, m.id ] }), {:include_blank => 'Choose a Menu'})
.control-group
=f.label :name, :class => 'control-label'
.controls
=f.text_field :name
.control-group
=f.label :category_ids, "Category", :class => 'control-label'
.controls
=f.collection_select :category_ids, (current_user.has_role? :admin) ? (Category.order(:name)) : (current_user.categories.order(:name)), :id, :name, params[:category_id].nil? ? {} : {:selected => params[:category_id]}, {multiple: true, :class => 'chzn-select'}
.controls
%p.help-block
=link_to_add_fields "Add New Category", f, :categories, "categories"
=link_to_add_fields
はファイルからネストされたフォームを生成し、この_category_fields.html.haml
関数は my で次のように定義されますapplication_helper.rd
。
def link_to_add_fields(name, f, association, parent)
new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, child_index: id) do |builder|
render(parent + "/" + association.to_s.singularize + "_fields", f: builder)
end
link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
end
私のcategory
部分的なフォーム ( _category_fields.html.haml
) では、次のようになります。
%fieldset
.control-group
%h5
New Category
=f.select("menu_id", (current_user.has_role? :admin) ? (Menu.all.collect {|m| [ m.name, m.id ] }) : (current_user.menus.all.collect {|m| [ m.name, m.id ] }), {:include_blank => 'Choose a Menu'})
=f.hidden_field :_destroy
=f.text_field :name, placeholder: "Name"
=link_to "X", "#", :class => "remove_fields"
お気づきのように、 はドロップダウン メニューからフォームでmenu_id
ユーザーによって既に選択および定義されています。dish
.control-group
=f.label :menu, :class => 'control-label'
.controls
=select("dish", "menu_id", (current_user.has_role? :admin) ? (Menu.all.collect {|m| [ m.name, m.id ] }) : (current_user.menus.all.collect {|m| [ m.name, m.id ] }), {:include_blank => 'Choose a Menu'})
しかし、ネストされたフォームから部分フォームmenu_id
内の別のドロップダウンを再選択するようにユーザーに強制していることにも気付きました。category
menu_id
ネストされたフォーム内でユーザーが再選択する必要がなく、代わりに、ユーザーが送信ボタンを押した後に、渡されるパラメーターからそれを検出しcategory
て新しいアイテムに割り当てられるようにしたいと思いますcategory
データベース。
たとえば、送信ボタンを押すと、ターミナル/コンソールに次のように表示されます。
Started POST "/dishes" for 127.0.0.1 at 2012-08-06 09:51:41 -0700
Processing by DishesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"tAbx+14Ve22FVimgY0x2d+fbImuG+pjkgC7Zgdco73k=", "dish"=>{"menu_id"=>"1", "name"=>"New Dish", "category_ids"=>["", "2"], "categories_attributes"=>{"1344271336031"=>{"menu_id"=>"1", "_destroy"=>"false", "name"=>""}} ... }}
繰り返しますが、をピックアップしてmenu_id
内を設定したいのです。"categories_attributes"=>{"1344271336031"=>{"menu_id"=>"1"...
"dish"=>{"menu_id"=>"1" ...
これを行う最善の方法はjQueryを使用することだと思いますが、jQueryに関しては完全な初心者であり、オンラインで調査するためにどこから始めて何を探すべきかわかりません。
私が試したもう 1 つのことは、作成後にコールバックを使用してデータベースを読み取ることでしたが、考慮しなければならない変数がたくさんあるため、安全ではありません。
更新 1: ほぼ完了しましたが、行き詰まりました
MurifoX ポインタのおかげで、 に割り当てられmenu_id
た.hidden_field
menu_id
dish
ただし、料理フォーム内に新しい料理と新しいカテゴリを作成しようとすると、新しいカテゴリ オブジェクトにカテゴリ ID が提供されていることを検証する、設定した検証エラーがスローされます。基本的に、は新しい Category オブジェクトのmenu_id
に渡されません。hidden_field
一方、次のことができます。
- 料理を編集し、ネストされたフォームから新しいカテゴリを作成します。
- 独自の _form.html.haml ページから新しいカテゴリを作成します。
- 既存のカテゴリ項目を編集します。
しかし、私は単にできません:
- ネストされたフォームから新しい料理と新しいカテゴリ項目を同時に作成します。
更新されたコードは次のとおりです。
_category_fields.html.haml
...
=f.hidden_field :menu_id, :value => @dish.nil? ? [:dish][:menu_id] : @dish.menu_id
...
カテゴリ_コントローラー.rb
def create
if @dish.blank?
@category = Category.new(params[:category])
else
@category = Category.new(:menu_id => [:dish][:menu_id], :name => [:category])
end
respond_to do |format|
if @category.save
format.html { redirect_to categories_path, notice: 'Category was successfully created.' }
else
format.html { render action: "new" }
end
end
end
def update
@category = Category.find(params[:id])
respond_to do |format|
if @dish.blank?
if @category.update_attributes(params[:category])
format.html { redirect_to categories_path, notice: 'Category was successfully updated.' }
else
format.html { render action: "edit" }
end
else
if @category.update_attributes(:menu_id => [:dish][:menu_id], :name => [:category])
format.html { redirect_to categories_path, notice: 'Category was successfully updated.' }
else
format.html { render action: "edit" }
end
end
end
end