Rails 4.2使用一个表单创建多个新记录

时间:2015-11-23 06:52:30

标签: forms ruby-on-rails-4

我有三个模型:课程,问题和答案。

我尝试做的是在节目课程视图中,显示问题并允许用户为每个答案创建答案。但是,我不确定最好的方法。

我在lesson#show视图中尝试了这种方法:

<% @questions.each do |question| %>
  <%= question.content %><br /><br />
  <%= simple_form_for :answers do |f| %>
    <%= f.input :content %>
    <%= f.hidden_field :question_id, :value => question.id %>
    <%= f.button :submit %>
  <% end %>
<% end %>

使用此代码,我收到错误param is missing or the value is empty: lesson

答案有两个字段:content,question_id。

我的另一个问题是我希望这对用户友好,所以如果有多个问题,答案应该有多个输入框(每个问题一个)和一个提交按钮(所以多个答案可以一次发布。)

我认为我的做法很糟糕,但我不确定如何做到这一点,所以任何帮助都会非常感激。

这是我到目前为止所拥有的:

型号:

class Lesson < ActiveRecord::Base
  has_many :questions, dependent: :destroy
  has_many :answers, through: :questions
  accepts_nested_attributes_for :questions, reject_if: :all_blank, allow_destroy: true
  accepts_nested_attributes_for :answers, reject_if: :all_blank, allow_destroy: true
end

class Question < ActiveRecord::Base
  belongs_to :lesson
  has_many :answers, dependent: :destroy
end

class Answer < ActiveRecord::Base
  belongs_to :question
end

课程控制器

class LessonsController < ApplicationController

  def show
    @questions = @lesson.questions
  end

  # PATCH/PUT /lessons/1
  # PATCH/PUT /lessons/1.json
  def update
    respond_to do |format|
      if @lesson.update(lesson_params)
        format.html { redirect_to @lesson, notice: 'Lesson was successfully updated.' }
        format.json { render :show, status: :ok, location: @lesson }
      else
        format.html { render :edit }
        format.json { render json: @lesson.errors, status: :unprocessable_entity }
      end
    end
  end     

 private

    def lesson_params
      params.require(:lesson).permit(:name,
      answers_attributes: [:id, :content, :question_id]
      )
    end
end

的routes.rb

resources :lessons
  post '/lessons/:id', to: "lessons#update"

3 个答案:

答案 0 :(得分:0)

在Gemfile中添加gem并运行bundle install: -

gem "nested_form"

on Lession show page: -

<%= nested_form_for @lession do |lession_form| %>
    <%= @lession.content %>        
    <%= lession_form.fields_for :questions do |question_form| %>
        <% @questions.each do |question| %>
            <%= question.content %><br /><br />
            <%= question_form.fields_for :answers do |answer_form| %>
                <%= answer_form.text_field :content %>
                <%= answer_form.link_to_remove "Remove this answer" %>
            <% end %>
            <%= question_form.link_to_add "Add more answer", :answers %>
        <% end %>
    <% end %>
    <%= lession_form.submit 'Update' %>
<% end %>

答案 1 :(得分:0)

我原本以为你可以在不使用宝石的情况下实现。

您可能需要在模型中指定inverse_of。我之前发现在处理表单时,嵌套属性中需要这样做。

class Question < ActiveRecord::Base
  belongs_to :lesson
  has_many :answers, dependent: :destroy, :inverse_of => :question
end

class Lesson < ActiveRecord::Base
  has_many :questions, dependent: :destroy, :inverse_of => :lessons
  has_many :answers, through: :questions
  #etc.
end

在您的课程控制器中:

def show
  @lesson = Question.find(params[:id])
  @questions = @lesson.questions
  x.times { @lesson.questions.answer.build }
end 

在您的观看次数/课程/显示页面中:

<%= form_for @lesson do |lesson| %>
  <%= @lesson.whatever_attribute %>
  <%= lesson.fields_for :questions do |question| %>
    <% @questions.each do |question| %>
      <%= question.content %>
    <% end %>
      <div id="answers-div" class='form-group'>
        <%= question_form.fields_for :answers do |answer| %>
          <%= answer.text_field :content id:"answer-entry" %>
        <% end %>
      </div>
  <% end %>
<% end %>
<%= lesson.submit 'Submit' %>

在表单下方添加一些按钮以添加更多答案或删除:

<button class="btn btn-default" id="addNewAnswer">Add Another Answer Box</button><br>
<button class="btn btn-default" id="deleteNewAnswer">Delete Last Answer</button>

然后你可以添加&amp;用jQuery动态删除答案。

$(document).ready(function(){
  $("#addNewAnswer").click(function() {
    $("#answers-div").append(createNewInputElement($("#answers-div")));
  });
});

function createNewInputElement(form) {
  var newIndex = $("#answers-div").children('input#choice-entry').length;
  var newInput = $("#answer-entry").clone().attr('name', generateNewInputName(newIndex));
  newInput.val('');
  return newInput;
 };

 function generateNewInputName(idx) {
   return "question[answers_attributes][" + idx + "][content]"
 };


 $(document).ready(function(){
   $("#deleteNewAnswer").click(function() {
     if ($("#answers-div input").length > 1) {
       $("#answers-div input:last-child").remove();
     }
   });
 });

使用嵌套表单不是问题。您需要嵌套表单才能在lessson.questions内嵌套答案,但您只允许用户提供输入

如果使用Rails 4(和强参数),你还需要在这些行中允许这些(否则将不允许传递的参数)。

private (in your Lessons controller)

def lesson_params
  params.require(:lesson).permit(:content, answer_attributes:[:content])
end

这可能不完美,但它是我希望的问题的某种解决方案的开始。

答案 2 :(得分:0)

尝试测试此代码,再次给我发电子邮件 在您的课程#show.html.erb

<% for question in @lesson.questions  %>
    <%= question.content %><br /><br />
    <%= simple_form_for :answers do |f| %>
      <%= f.input :content %>
      <%= f.hidden_field :question_id, :value => question.id %>
      <%= f.button :submit %>
    <% end %>
<% end %>