2

我有一个相当简单的 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

4

2 回答 2

1

@exam.problems 是一个对象列表,但由于关系,您的考试中还应该有一个setter 方法,所以problem_ids

@exam.update_attributes(params[:exam])

应该做你想做的。如果您出于某种原因需要更新 problem_ids,这应该可以解决问题:

@exam.update_attribute(:problem_ids, params[:exam][:problem_ids])

注意:我省略了 rails4 strong_parameters 以使答案对 rails 3 或 4 通用,请确保您使用适合您的版本的方法。

于 2013-12-17T19:17:18.713 回答
0

感谢您的所有帮助,但我终于自己弄清楚了。问题是,即使我允许problem_ids作为参数传递,我并没有告诉控制器它实际上是一个数组。因此,一旦我将相关行更改为:

@exam.update_attributes(params[:exam].permit(:title, problem_ids: []))

它工作得很好!

于 2013-12-24T19:42:59.687 回答