如何在一个Rails表单中处理多个模型?

13

我有以下模型

class Survey < ActiveRecord::Base
  has_many :survey_sections
  accepts_nested_attributes_for :survey_sections
end

class SurveySection < ActiveRecord::Base
  belongs_to :survey
  has_many :questions
  accepts_nested_attributes_for :questions
end

class Question < ActiveRecord::Base
  belongs_to :survey_section
  has_many :answers
  belongs_to :question_group
  accepts_nested_attributes_for :question_group
  accepts_nested_attributes_for :answers
end

class Answer < ActiveRecord::Base
  belongs_to :question
end

class QuestionGroup < ActiveRecord::Base
  has_many :questions
end

我的控制器:

 def new
    @survey = Survey.new
    survey_section = @survey.survey_sections.build
    survey_section.questions.build
  end

 def create
    @survey = Survey.new(survey_params)
    if @survey.save
      redirect_to @survey, notice: 'Super'
    else
      render 'new'
    end
  end

 def survey_params
      params.require(:survey).permit(:title, :description, survey_sections_attributes:[:id, :title, questions_attributes:[:id, :text, answers_attributes:[:id, :text]]])
    end

如何在三个以上的模型中保存数据?目前,我可以将调查表格中的数据保存到调查、调查部分和问题模型中。但我不知道在控制器中应该怎么做才能将数据保存到其他模型中。


1
我的建议是尽量避免使用嵌套表单。虽然这是所谓的Rails方式,但它会大大增加复杂性和耦合度。最好手工创建表单并使用表单对象来处理它。你可以在Google上搜索这种方法。 - vladra
2个回答

20

如果你正确使用fields_for辅助工具,你可以处理所需数量的表单。

我认为这就是你存在问题的地方(你的控制器看起来还好)。

我也曾在一段时间前写过答案关于此事。

#app/models/survey.rb
class Survey < ActiveRecord::Base
    has_many :sections
    accepts_nested_attributes_for :sections
end

#app/models/section.rb
class Section < ActiveRecord::Base
    belongs_to :survey
    has_many :questions
    accepts_nested_attributes_for :questions
end

#app/models/question.rb
class Question < ActiveRecord::Base
    belongs_to :section
    has_many :answers
end

尽量让你的模型名称简洁。

#app/controllers/surveys_controller.rb
class SurveysController < ApplicationController
   def new
      @survey = Survey.new
      @survey.sections.build.questions.build
   end

   def create
      @survey = Survey.new survey_params
      @survey.save
   end

   private 

   def survey_params
      params.require(:survey).permit(:title, sections_attributes: [:title, questions_attributes:[:title]])
   end
end

#app/views/surveys/new.html.erb
<%= form_for @survey do |f| %>
   <%= f.text_field :title %>
   <%= f.fields_for :sections do |section| %>
       <%= section.text_field :title %>
       <%= section.fields_for :questions do |question| %>
           <%= question.text_field :title %>
       <% end %>
   <% end %> 
   <%= f.submit %>
<% end %>

4
我花了半个小时和大约40个Chrome标签页,最终找到了这个答案,只花了2分钟就解决了我的问题。谢谢! - stevec

1

您可以在此处获得与相同类型的模型相同的最佳解释

http://railscasts.com/episodes/196-nested-model-form-part-1

#app/models/survey.rb
class Survey < ActiveRecord::Base
    has_many :sections, :dependent => :destroy
    accepts_nested_attributes_for :sections, :allow_destroy => true
end

#app/models/section.rb
class Section < ActiveRecord::Base
    belongs_to :survey
    has_many :questions, :dependent => :destroy
    accepts_nested_attributes_for :questions, :allow_destroy => true
end

#app/models/question.rb
class Question < ActiveRecord::Base
    belongs_to :section
    has_many :answers
end

现在在控制器中。
def new
  @survey = Survey.new
  section = @survey.sections.build
  section.questions.build 
  end
end

现在在视图中。
<%= form_for @survey do |f| %>
  <%= f.error_messages %>
  <p>
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </p>
  <%= f.fields_for :sections do |builder| %>
     <%= builder.text_field :title %>
     <%= builder.fields_for :questions do |question| %>
        <%=  question.text_field :content%>
     <% end %>
  <% end %>
  <p><%= f.submit "Submit" %></p>
<% end %>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接