我在我的 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:几乎就在那里,但卡住了
多亏了 MurifoX 指针,我可以menu_id
通过hidden_field
在嵌套表单中menu_id
分配dish
.
但是,当我在菜式表单中创建一个新的 Dish 和一个新的 Category 时,它会抛出我设置的验证错误,该错误验证是否已为新的 Category 对象提供了一个类别 ID。所以基本上,menu_id
没有被传递到hidden_field
新的 Category 对象中。
另一方面,我能够:
- 编辑 Dish 并从嵌套表单创建一个新类别。
- 从其自己的 _form.html.haml 页面创建一个新类别。
- 并编辑现有的类别项目。
但我根本不能:
- 同时从嵌套表单创建一个新的 Dish 和一个新的 Category 项。
这是我更新的代码:
_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