我有一个Sezzion
模型:
attr_accessible :description
has_many :session_instructors, :dependent => :destroy
has_many :instructors, :through => :session_instructors
accepts_nested_attributes_for :session_instructors
accepts_nested_attributes_for :instructors
Instructor
型号:
attr_accessible :bio
has_many :sezzions, :through => :session_instructors
has_many :session_instructors, :dependent => :destroy
SessionInstructor
型号:
attr_accessible :instructor_id, :sezzion_id
belongs_to :sezzion
belongs_to :instructor
最后,User
模型:
has_many :sezzions
has_many :instructors
我正在尝试为Sezzion
创建一个带有嵌套表单的表单SessionInstructor
该表单具有Instructors
的多个选择选项。
我该如何执行以下操作:
SessionInstructor
的嵌套表单- 使用多选选项获取所有选定的
Instructor
instructor_id
- 要与每个选定讲师一起传入创建/更新
session_id
的隐藏字段
到目前为止,我有以下代码:
<%= form_for(@sezzion) do |f| %>
<%= f.label :description %>
<%= f.text_area :description %>
<%= f.label :instructors %>
<%= fields_for :session_instructors do |f| %>
<select multiple>
<% current_user.instructors.each do |instructor| %>
<option><%= instructor.name %></option>
<% end %>
</select>
<% end %>
<%= f.submit %>
<% end %>
非常感谢!
Rails 中似乎非常困难。
我认为这样的事情可能会起作用:
<%= f.fields_for :session_instructors do |si| %>
<%= si.collection_select :instructor_ids, current_user.instructors, :id, :name, multiple: true>
<% end %>
这应该创建一个表单元素来设置 sezzion[session_instructors_attributes][instructor_ids]。
虽然我不确定这是否真的是你想要的。我从未尝试过使用多选。如果它不起作用,您也可以尝试摆脱fields_for
并仅使用 f.collection_select
.如果您愿意使用复选框,我可以肯定地向您展示如何做到这一点。
我希望这有所帮助。
编辑:
以下是我通常使用check_box
的方式:
<%= f.fields_for :session_instructors do |si| %>
<%= si.hidden_field "instructor_ids[]" %>
<% current_user.instructors.each do |i| %>
<%= si.check_box "instructor_ids[]", i.id, i.sezzions.include?(@sezzion), id: "instructor_ids_#{i.id}" %>
<%= label_tag "instructor_ids_#{i.id}", i.name %>
<% end %>
<% end%>
这种方法有几个"陷阱!编辑模型时,如果取消选中所有复选框,则根本不会发送参数。这就是为什么hidden_field
是必要的。此外,您需要确保每个表单元素都有唯一的id
字段。否则,仅发送最后一个条目。这就是我自己手动设置值的原因。
我复制粘贴然后编辑。希望我的语法足够接近,你可以让它工作。
最终编辑:
根据Sayanee下面的评论,答案比我想象的要简单一些:
<%= f.collection_select :instructor_ids, current_user.instructors, :id, :name, {}, {:multiple => true} %>
@Sayanee,你能发布你的导师,sezzions表的样子吗?另外请注意,您无法从讲师对象获取instructor_ids,因此您会收到"未定义的方法"错误。使用您共享的当前关联,您可以从 Sezzion 对象获取instructor_ids。所以你需要循环遍历current_user.sezzions而不是current_user.instructors。
has_many :through 关联的情况下使用 html multiple_select实现fields_for嵌套表单的方法。通过做这样的事情解决了它。表单视图:
<%= form_for(@sezzion) do |f| %>
...
<%= fields_for :session_instructors do |g| %>
<%= g.label :instructor, "Instructees List (Ctrl+Click to select multiple)" %>:
<%= g.select(:instructor_id, Instructor.all.collect { |m| [m.name, m.id] }, {}, { :multiple => true, :size => 5 }) %>
<%= g.hidden_field :your_chosen_variable_id, value: your_chosen.id %>
<% end %>
...
<%= f.submit %>
<% end %>
注意:由于@sezzion在生成表单时不会保存,因此您无法通过表单传递该 id (@sezzion.id) 代替 your_chosen.id。您可以在控制器中处理该保存。
确保您的控制器在生成表单时初始化变量: 您的 def new 可能如下所示:
def new
@sezzion = Sezzion.new
@sezzion.session_instructor.build
@sezzion.instructors.build
end
现在,创建控制器必须能够接受多选所需的强参数,因此sezzion_params方法可能如下所示:
def sezzion_params
params.require(:sezzion).permit(:description, :any_other_fields,
:session_instructors_attributes =>
[:instructor_id => [], :your_chosen_id => Integer])
end
在 create 函数中,第一个 session_instructor 变量通过我们的新函数链接到@sezzion实例变量。如果要将创建的 @sezzion.id 与每个选择讲师一起传入,则必须在保存 Sezzion 实例后构建我们的多项选择中的其他session_instructors。.
def create
@sezzion = Sezzion.new(sezzion_params)
@startcount=1 #The first element of the array passed back from the form with multiple select is blank
@sezzion.session_instructors.each do |m|
m.instructor_id = sezzion_params["session_instructors_attributes"]["0"]["instructor_id"][@startcount]
m.your_chosen_variable_id = your_chosen.id
@startcount +=1
end
if @sezzion.save
sezzion_params["session_instructors_attributes"]["0"]["instructor_id"].drop(@startcount).each do |m|
@sezzion.session_instructors.build(:instructor_id => sezzion_params["session_instructors_attributes"]["0"]["instructor_id"][@startcount],
:your_chosen_variable_id => your_chosen.id).save
@startcount += 1
end
flash[:success] = "Sezzion created!"
redirect_to root_url
else
flash[:danger] = "There were errors in your submission"
redirect_to new_sezzion_path
end
end