我正在构建一个创建考试的应用程序。对于用户在考试中选择答案的部分,我想使用复选框(或单选按钮)来允许他们选择答案。
我希望所有用户选择的答案都是一个称为“响应”的表。我无法弄清楚如何使用单选按钮来创建记录。
所有响应记录需要的是获取考试,用户和分数的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动作参加考试。然后他们会有一个属于他们的分数。
答案 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)