我有一个像Rails Survey Gem(runtimerevolution)这样的评估模型,老师为学生创建MCQ评估。它的选项是单选按钮类型。有一个选项是正确的。
当学生申请MCQ评估时,会得到一个问题文件,其中Question有多个选项,学生通过单选按钮选择一个选项。
所以我只想在我的新模型尝试中存储关于question_id的选定option_id。
这是适用于学生的MCQ页面。
<div class="stream-cont">
<%= form_tag(action: "apply") do %>
<% @mcq.questions.each_with_index do |q, i| %>
<div class="feed-cont-title all-header">
<p>
<%="Question-#{i+1}: "+ q.question %>
</p>
<p>
<strong>Answer : </strong>
<%=
collection_radio_buttons("questions[#{q.id}]", :option_id, q.options, :id, :option) do |b|
b.label(style: "display:block") { b.radio_button + b.text }
end
%>
</p>
</div>
<% end %>
<% end %>
<%= submit_tag "Submit Answer", :class => "typeD button" %>
</div>
这是Mcq控制器
def apply
@club = current_user.clubs
if current_user.user_type == User::User_types[:student]
@mcq = Mcq.find(params[:id])
end
@attempt = current_user.attempts.new
@mcq = Mcq.find(params[:id])
@attempt = current_user.attempts.new(attempt_params)
@attempt.save
redirect_to attempt_id(@attempt.id), notice: "Thank you"
end
Private
def attempt_params
params.require(:attempt).permit(:user_id, :mcq_id, :question_id, :option_id)
end
end
它不完整,我知道它是不正确的。我只是想知道如何选择关于question_id的Option_id并将此值保存在尝试模型的option_id列中。
我知道如何管理它以及在视图和控制器中应该使用什么。
答案 0 :(得分:1)
首先,为什么你有apply
方法?
Rails在很大程度上依赖于CRUD
基础设施;您的请求应该进入与applications
模型相关联的Application
控制器:
#app/models/application.rb
class Application < ActiveRecord::Base
#columns id | mcq_id | user_id | created_at | updated_at
belongs_to :mcq
belongs_to :user
has_many :answers, class: "ApplicationAnswer"
accepts_nested_attributes_for :answers
end
#app/models/application_answer.rb
class ApplicationAnswer < ActiveRecord::Base
#columns id | application_id | question_id | answer_id | created_at | updated_at
belongs_to :application
belongs_to :question
belongs_to :answer
end
#app/models/mcq.rb
class MCQ < ActiveRecord::Base
has_many :applications
has_many :questions
has_many :answers, through: :questions
end
#app/models/question.rb
class Question < ActiveRecord::Base
#columns id | mcq_id | etc | etc
belongs_to :mcq
has_many :answers
accepts_nested_attributes_for :answers #-> you can make a nested form; each time you make a question, you can make answers
end
#app/models/answer.rb
class Answer < ActiveRecord::Base
#columns id | question_id | value | created_at
belongs_to :question
end
看起来很复杂;它只是按如下方式分割你的数据:
MCQ
(问题集和可能的答案)Applications
(用户提供详细信息,例如为什么要加入等)ApplicationAnswers
(用户对问题的回答。单独的模型以提供可扩展性(IE可以为每个问题添加尽可能多的答案)- 醇>
Questions
(与MCQ绑定;提供添加问题和分配答案的功能)。
-
这意味着您可以执行以下操作:
#config/routes.rb
resources :mcqs, only [:show] do
resources :applications, only: [:new, :create] #-> url.com/mcq/:id/applications/new
end
#app/controllers/applications_controller.rb
class ApplicationsController < ApplicationController
def new
@mcq = MCQ.find params[:id]
end
def create
@mcq = MCQ.find params[:id]
@application = @mcq.applications.new application_params
if @application.save
# ...
else
# ...
end
end
private
def application_params
params.require(:application).permit(:application, :params, :mcq_id, answer_params: [:question_id, :application_id, :answer_id]).merge(user_id: current_user.id)
end
end
现在,您要创建的表单可以通过 ApplicationAnswers
保存Application
:
#app/views/applications/new.html.erb
<%= form_for @mcq.applications.new do |f| %>
<%= f.text_field :your_mcq_stuff_here %>
<%= f.fields_for :answers, @mcq.questions do |question| %>
<%= question.hidden_field :question_id, question.id %>
<%= question.collection_radio_buttons :answer_id, question.answers.all, :id, :value %>
<%= f.submit %>
<% end %>
<% end %>
此处的一些问题包括n+1
查询问题,以及我未对其进行过测试的事实。
-
如果这种情况正常,您基本上可以让users
能够向Application
提交MCQ
。每个MCQ
都会有一系列Questions
,这些问题会有一系列Answers
。
这可能需要调整;这是我用于此类项目的结构。
答案 1 :(得分:0)
Mcq实际上是这里的顶级模型,而不是Attempt,所以我认为嵌套会造成一些混乱。
在这种情况下,您可以利用form_for和fields_for,它将为您嵌套params哈希。它看起来像这样:
<%= form_for @mcq do |f| %>
<% f.fields_for :question |question_fields, i| %>
<div class="feed-cont-title all-header">
<p>
<%="Question-#{i+1}: "+ question_fields.object %>
</p>
<p>
<strong>Answer : </strong>
<% question_fields.fields_for :option |option_fields| %>
<%= option_fields.radio_button(:id) %>
<%= option_fields.label(:name) %>
<% end %>
</p>
</div>
<% end %>
<% end %>
然后,您希望控制器将参数列入白名单,如:
Private
def mcq_params
params.require(:mcq).permit(:user_id, :mcq_id, questions_attributes[ :id, :options_attributes[:id]])
end
当您提交表单时,您的参数将类似于
:mcq[:user_id, :id, questions_attributes[][:id, :options_attributes[:id]]
此时,您只需遍历问题属性哈希来构建用户的尝试对象。
很抱歉,如果代码没有被发现 - 我不确定我是否完全理解问题和选项之间的关系,但这应该让你走上正轨。如果它太不太明显,你可以保留单选按钮集合,我发现随着时间的推移,表单往往会变得复杂,所以让导轨为你嵌套是很好的。