如何在模型中保存选定的单选按钮值

时间:2015-09-23 08:06:29

标签: ruby-on-rails

我有一个像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列中。

我知道如何管理它以及在视图和控制器中应该使用什么。

2 个答案:

答案 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

看起来很复杂;它只是按如下方式分割你的数据:

  
      
  1. MCQ(问题集和可能的答案)
  2.   
  3. Applications(用户提供详细信息,例如为什么要加入等)
  4.   
  5. ApplicationAnswers(用户对问题的回答。单独的模型以提供可扩展性(IE可以为每个问题添加尽可能多的答案)
  6.   
  7. Questions(与MCQ绑定;提供添加问题和分配答案的功能)。
  8.   

-

这意味着您可以执行以下操作:

#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]]

此时,您只需遍历问题属性哈希来构建用户的尝试对象。

很抱歉,如果代码没有被发现 - 我不确定我是否完全理解问题和选项之间的关系,但这应该让你走上正轨。如果它太不太明显,你可以保留单选按钮集合,我发现随着时间的推移,表单往往会变得复杂,所以让导轨为你嵌套是很好的。