我有一个相当简单的 Rails 应用程序,它可以做数学测验。用户可以通过问题和答案创建数学问题。他们还可以创建带有标题的考试。模型与 has_many_and_belongs_to 关系链接,因为每个测验可以有很多问题,每个问题可以属于许多测验。这种关系似乎运作良好,因为当我删除问题或考试时,相关对象列表会更新。我目前拥有的方式是,当您创建考试时,视图会为您提供一个复选框列表,每个复选框对应问题数据库中的每个问题。用户单击他们想要在考试中出现的问题的复选框,无论选中哪个复选框,这些问题都会添加到考试中。我将展示更新的代码,因为这是我一直用来测试的视图。
这是视图:
<h2>Available Problems:</h2>
<% Problem.all.each do |prob| %>
<%= f.fields_for "exam[problem_ids][]", prob do |builder| %>
<p>
<%= check_box_tag "exam[problem_ids][]", prob.id, @exam.problems.include?(prob) %>
<%= prob.question %> = <%= prob.answer %> | <%= link_to "Edit", edit_problem_path(prob) %>
</p>
<% end %>
<% end %>
我必须使用check_box_tag
,因为如果我尝试使用builder.check_box
,它不会保存已选中的框。
我的控制器:
def update
@exam = Exam.find(params[:id])
if @exam.update_attributes(params[:exam].permit(:title, :problem_ids))
redirect_to @exam
else
render 'edit'
end
end
在视图中,我将所有复选框结果保存在了 question_ids 数组中。我知道该数组已正确填充,因为当我添加以下代码时,它可以工作。
@exam.problems = []
params[:exam][:problem_ids].each {
|prob_id|
@exam.problems << Problem.find(prob_id)
}
显然,这是一种非常老套的方法,因为我每次都手动构建问题列表,但我一生都无法弄清楚如何让这些复选框结果自动填充到update_attributes
方法中。有任何想法吗?
更新:根据下面多诺万的建议,我在我的考试模型中实现了以下方法:
def problem_ids=(some_problem_ids)
@exam.problems.clear
some_problem_ids.each {
|prob_id|
@exam.problems << Problem.find(prob_id)
}
end
据我了解,这应该是problem_ids
. 可悲的是,当我在考试控制器中使用以下行时,问题列表仍未更新:
@exam.update_attributes(params[:exam].permit(:title, :problem_ids))
PS我必须把.permit(:title, :problem_ids)
位,否则我会得到一个ForbiddenAttributesError
。