我有一个相当简单的rails应用程序,可以处理数学测验。用户可以创建一个问题和一个答案的数学问题。他们还可以创建带有标题的考试模型与has_many_和_belong_to relationship联系在一起,因为每个测验可能有许多问题,每个问题可能属于许多测验。这种关系似乎很好,因为当我删除问题或考试时,相关的对象列表会更新。我现在的方法是,当你创建一个考试时,视图会给你一个复选框列表,在问题数据库中每个问题都有一个。用户单击复选框以查找他们希望在考试中出现的问题,无论选中哪个复选框,这些问题都会添加到考试中。我将显示更新的代码,因为这是我一直用来测试的视图。
这是景色:
<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)
}
显然,这是一种非常骇人的方法,因为我每次都手动构建问题列表,但我一辈子都搞不懂如何让这些复选框结果自动填充到
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
的“setter”方法遗憾的是,当我在考试控制器中使用以下行时,问题列表仍然没有更新:@exam.update_attributes(params[:exam].permit(:title, :problem_ids))
注意,我必须把
.permit(:title, :problem_ids)
位放进去,否则我会得到ForbiddenAttributesError
。 最佳答案
@exam.problems是一个对象列表,但是由于这种关系,在您的考试中还应该有一个problem_ids
setter方法,所以
@exam.update_attributes(params[:exam])
应该做你想做的如果出于某种原因,您只需要更新问题ID,那么这就可以做到:
@exam.update_attribute(:problem_ids, params[:exam][:problem_ids])
注意:我省略了rails4 strong_参数,以使答案对于rails 3或rails4是通用的,确保您对您的版本使用了适当的方法。