我有一个相当简单的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
在视图中,我将所有复选框结果保存在problem_ids数组中。我知道这个数组正在被正确填充,因为当我添加以下代码时,它可以正常工作。
@exam.problems = []
params[:exam][:problem_ids].each {
|prob_id|
@exam.problems << Problem.find(prob_id)
}
显然,这是一种非常hackey的方法,因为我每次手动构建问题列表,但我不能为我的生活弄清楚如何让那些复选框结果自动填充在{ {1}}方法。有什么想法吗?
更新: 根据Donovan的建议,我在考试模型中实施了以下方法:
update_attributes
据我了解,这应该是 def problem_ids=(some_problem_ids)
@exam.problems.clear
some_problem_ids.each {
|prob_id|
@exam.problems << Problem.find(prob_id)
}
end
的“setter”方法。遗憾的是,当我在考试控制器中使用以下行时,问题列表仍未更新:
problem_ids
P.S。我必须放@exam.update_attributes(params[:exam].permit(:title, :problem_ids))
位,否则我会得到.permit(:title, :problem_ids)
。
答案 0 :(得分:1)
@ exam.problems是一个对象列表,但由于这种关系, 也应该在您的考试中使用problem_ids
setter方法,所以
@exam.update_attributes(params[:exam])
应该做你想做的事。如果由于某种原因你只需要 更新problem_ids,这应该可以解决问题:
@exam.update_attribute(:problem_ids, params[:exam][:problem_ids])
注意:我省略了rails4 strong_parameters以使rails 3或4的答案通用,请确保为您的版本使用适当的方法。
答案 1 :(得分:0)
感谢您的帮助,但我终于自己想出来了。问题是,即使我允许problem_ids
作为参数传递,我也没有告诉控制器它实际上是一个数组。所以,一旦我将相关的行改为:
@exam.update_attributes(params[:exam].permit(:title, problem_ids: []))
它完美无缺!