接受模型中的嵌套属性,其中包含与其自身无关的其他模型

时间:2015-10-13 02:37:48

标签: ruby-on-rails ruby-on-rails-4 nested-forms

好吧,我有一个小问题,我不是。我知道我已接近解决这个问题,但我需要一些帮助。好吧,基本上我创建的是一个允许用户提交调查的网站,然后允许人们回答这些调查。所以我创建了一个使用问题的调查模型,这些问题使用了答案。当用户创建调查时,他只创建调查和问题,之后通过另一个称为结果的模型创建答案。我遇到的麻烦是通过结果表单将这些答案作为问题的一部分提交。所以这是我的结果控制器:

class ResultsController < ApplicationController
  before_action :set_result, only: [:show]

  def show
    @survey = Survey.find(params[:survey_id])
  end

  def new
    @survey = Survey.find(params[:survey_id])
    @survey.questions.all.each do |question|
      question.build_answer
    end 
    @result = @survey.results.build
  end

  def create
    @survey = Survey.find(params[:survey_id])
    @result = @survey.results.build

    respond_to do |format|
      if @result.save
        format.html { redirect_to survey_result_path(@result), notice: 'Survey was successfully answered.' }
      else
        format.html { render :new }
      end
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_result
      @result = Result.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def result_params
      params.require(:result).permit(:survey_id)
    end
end

因此,在我的表格中,我试图将答案作为问题的一部分而不是结果提交。

这是看起来的样子:

<%= form_for([@survey, @result]) do |f| %>
  <% if @result.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@result.errors.count, "error") %> prohibited this result from being saved:</h2>

      <ul>
      <% @result.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>
  <% for question in @survey.questions  %>   
    <div class="field">
      <label><%= question.question_content %></label>
        <%= fields_for :answer, question.build_answer do |builder| %>
          <%= builder.text_field :answer_content, placeholder: "Answer"%>
        <% end %>
    </div>
  <% end %>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

无论如何,这是相关部分:

<% for question in @survey.questions  %>   
        <div class="field">
          <label><%= question.question_content %></label>
            <%= fields_for :answer, question.build_answer do |builder| %>
              <%= builder.text_field :answer_content, placeholder: "Answer"%>
            <% end %>
         </div>

我还应该提一下,问题和答案没有控制器,它们只是模型,我不需要任何视图或控制器,没有任何理由让它们组件。

我不知道答案和问题是否与结果无关。如果最好改变它,那么我会这样做,但到目前为止,这是我遇到过的唯一问题。如果有人能帮我这个,我很感激,这是一个长期困难项目的最后一步。

1 个答案:

答案 0 :(得分:0)

我接受你的话,你已经尝试过@max的建议,看看这已经完成了 - 我同意@max看到人们已经解决了它会给你一个比我更好的答案我找到了你。但是,如果你已经尝试过,那么这可能会有所帮助。

这不是您问题的答案,但它可能是您问题的解决方案。我同意@ max的第一个评论 - 看起来你正试图用那个控制器做太多。如果是我,我会做一些重构,看看你的整体设计,而不是解决这个特定的问题。

这是我的建议。 (免责声明:我没有重新创建你的项目来测试它,或者提供了足够详细的信息来逐步指导它。)这只是另一种解决问题的方法。我认为通过简化每个控制器必须做的事情会使你的问题消失。

建议

  • 拆分您的控制器 - SurveysControllerResultsController,如@max建议
  • Result课程与Survey课程相关联(可能是调查has_many :results,如果一项调查可以多次完成)
  • 从路由的角度来看,使用nested resources将结果作为Survey的子项(因此您的网址可能看起来像http://yoursite.com/survey/12/result/2,以查看调查#12的第二组答案)
  • 从“调查”视图中,链接到新的“结果”路线,作为“回复调查”链接。换句话说,通过创建属于相关调查的新结果来回答调查。将使用与用于调查创建和管理的控制器不同的控制器创建,编辑和保存此新结果
  • 来自结果模型的
  • 关键部分:,当您创建新结果时,使用回调为相关调查中的每个问题创建一个答案(但现在将答案文本留空)[见下面的result.rb片段]
  • 从视图中,允许用户为每个空答案提供文字[请参阅下面的观点/结果/ edit.html.erb代码段]
  • 显示结果时,将调查问题ID与结果答案相匹配 IDS

在result.rb

after_initialize :create_answers

def create_answers
  return unless self.new_record? # don't create them if it isn't a new record
  self.survey.questions.each_with_index do |q,i|
    self.answers.create(question_index: i)
  end
end

在views / results / edit.html.erb

<% @result.answers.each_with_index do |a,i| %>
  <!-- label the answer with: -->
  <%= @result.survey.questions[i] %>
  <!-- render the form field for: --> 
  <%= a.text %>
<% end %>
来自http://yoursite.com/survey/12/result/2 访问的views / results / show.html.erb中的

<dl>
<% @result.survey.questions.each_with_index do |q,i| %>
  <dt class="question"><%= q.text %></dt>
  <dd class="answer"><%= @result.answers[i] %></dd>
<% end %>
</dl>

摘要

这使您可以使用相同的基本控制器逻辑来创建保存结果时的调查。您让模型处理匹配问题与答案,然后控制器只需处理结果及其子答案,或调查及其子问题。

同样,不是一个完整的解决方案,但希望有一些想法可以帮助你继续前进。

进一步改进

这仍然有点难看 - @result.survey.questions[index]不是很干净。如果是我,我会让一切正常工作,然后以某种方式将@result.survey.questions[index]内容重构到Result模型中 - 可能是:Result#question_answer_pairs返回一个2D数组(但仍然不是很干净)。或者,使用ActiveRecord将每个答案与相应的问题相关联,这样您就可以并排使用answer.textanswer.question_text