复选框在rails

时间:2018-02-25 00:33:30

标签: ruby-on-rails checkbox nested-forms nested-attributes

我正在构建一个创建考试的应用程序。对于用户在考试中选择答案的部分,我想使用复选框(或单选按钮)来允许他们选择答案。

我希望所有用户选择的答案都是一个称为“响应”的表。我无法弄清楚如何使用单选按钮来创建记录。

所有响应记录需要的是获取考试,用户和分数的ID。分数是一个跟踪用户分数和正确答案数量的表。 这是我的考试模式(rails不会让我使用“考试”这个词)。我为嵌套属性设置了它。

class Examination < ApplicationRecord
  belongs_to :user
  has_many :questions, dependent: :destroy
  has_many :scores
  has_many :responses
  has_secure_password

  accepts_nested_attributes_for :responses, allow_destroy: true
end

响应模型非常基础:

class Response < ApplicationRecord
  belongs_to :user
  belongs_to :score
  belongs_to :examination
end

这是“参加考试”页面:     &lt;%= link_to“返回所有考试”,examinations_path%&gt;

<h2><%= @exam.name %></h2>
<h3><%= @exam.intro %></h3>

<%= form_for @exam  do |f| %>
  <%= f.hidden_field :name, value: @exam.name  %>
  <%= fields_for :responses do |res_f| %>
    <% @exam.questions.each_with_index do |question, i| %>
      <% index = i + 1 %>
      <h2>Question #<%=index%></h2><span style="font-size: 24px; font-weight: normal">(<%= question.points %> Points)</span>
      <hr>
      <h3><%= question.body %></h3>
      <% question.answers.each do |ans| %>
        <table>
          <tr>
            <td><%= res_f.check_box :answer_id , ans.id, :examination_id , @exam.id, :user_id  %></td>
            <td><%= ans.body %></td>
          </tr>
        </table>
      <% end %>
    <% end %>
  <% end %>

  <%= f.submit 'Submit' %>
<% end %>

此代码无法运行,因为Rails希望响应记录存在以便使用该表单。它抛出了这个错误:

undefined method `merge' for 484:Integer

如果我将此复选框代码调整为:

<%= res_f.check_box :answer_id  %>

代码将运行,它将在提交时提供以下参数:

Started PATCH "/examinations/34" for 127.0.0.1 at 2018-02-24 16:22:41 -0800
Processing by ExaminationsController#update as HTML
      Parameters: {"utf8"=>"✓", "authenticity_token"=>"y4vcPByUKnDdM6NsWDhwxh8MxJLZU4TQo+/fUrmKYEfb3qLn5FVieJAYirNRaSl0w5hJax20w5Ycs/wz1bMEKw==", "examination"=>{"name"=>"Samuel Smith’s Oatmeal Stout"}, "responses"=>{"answer_id"=>"1"}, "commit"=>"Submit", "id"=>"34"}

我知道这不对,但我希望它至少会创造一个记录。所有复选框都必须创建响应记录。它应该能够获取answer_id,exam_id和user_id。就是这样。

有谁知道怎么做?

编辑以回应Pablo 7: 以下是其他模型(它们现在非常基本)

class Score < ApplicationRecord
  belongs_to :user
  belongs_to :examination
  has_many :responses, dependent: :destroy
end

class User < ApplicationRecord
  has_many :examinations, dependent: :destroy
  has_many :scores, dependent: :destroy
  has_many :responses, dependent: :destroy

  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
end

class Question < ApplicationRecord
    belongs_to :examination
    has_many :answers, dependent: :destroy

    accepts_nested_attributes_for :answers, allow_destroy: true

    validates_presence_of :body
    validates_presence_of :question_type
end

@exam和考试是一样的。考试控制器中有一个“采取”动作,允许用户参加考试:

def take
    @exam = Examination.find(params[:id])
    @score = @exam.scores.build
    @score.user_id = current_user.id
    @score.save
end

因此,考试属于创建它的用户。相同的用户或不同的用户可以使用take动作参加考试。然后他们会有一个属于他们的分数。

1 个答案:

答案 0 :(得分:1)

我认为您必须对模型进行一些更改:

  • 答案应该属于一个问题(这是用户正在回答的问题)。

  • 响应应该属于答案(它是问题的正确答案;用户检查的答案)。如果您想允许多个正确答案,则应更改此答案。

  • 答案不应属于考试,不应属于用户。事实上,响应属于分数而且足够,因为分数已经属于考试和用户。

  • 考试不应该有很多回复。事实上,考试有很多分数,分数有很多回答。如果需要,您可以使用has_many :responses, through: :scores

  • 用户不应该有很多回复。他们有很多分数和分数有很多回应。如果需要,您可以使用has_many :responses, through: :scores

当你创建一个新的分数(in take)时,你应该为考试中的每个问题创建空的答案:

def take
  @exam = Examination.find(params[:id])
  @score = @exam.scores.build(user_id: current_user.id)
  @exam.questions.each { |question| @score.responses.build(question_id: question.id) }

  #I don't think you should save here. 
  #This method is like the new method
  #You should save when the score is submitted
  #@score.save 
end

以您的形式: 我会将表格改为评分模型(不是考试)。如果您使用的是嵌套路由,则可能是[@exam,@ score]

这可能有很多错误,因为我现在无法测试。我希望这个想法很明确:

<%= form_for @score do |f| %>
  <%= f.hidden_field :name, value: @score.examination.name  %>
  <% @score.responses.each_with_index do |response, i| %>
    <%= f.fields_for response do |res_f| %>
      <% index = i + 1 %>
      <h2>Question #<%= index %></h2>
      <span style="font-size: 24px; font-weight: normal">
        (<%= response.question.points %> Points)
      </span>
      <hr>
      <h3><%= response.question.body %></h3>
      <%= res_f.collection_radio_buttons :answer_id, response.question.answers, :id, :body %>
    <% end %>
  <% end %>

  <%= f.submit 'Submit' %>
<% end %>

提交应调用Score模型中的方法来创建Score(ScoresController.create)