如何使用继承和嵌套属性构建Rails表单?

时间:2013-11-17 20:22:11

标签: ruby-on-rails inheritance activerecord ruby-on-rails-4 nested-attributes

我有一个调查应用程序,基本上与Railscast 196一致,但有一个障碍:Railscast有一个Question类,has_many :answers,我有几个:

Question (self.abstract_class = true)
BasicQuestion < Question
MultipleChoiceQuestion < Question

为了完成这项工作,我不得不覆盖questions Survey中的Survey.rb has_many :questions accepts_nested_attributes_for :questions def questions # simplified a bit for brevity questions = [] [BasicQuestion, LikertQuestion, MultipleChoiceQuestion].each do |model| questions += model.where(:survey_id => self.id) end questions end Survey_Controller.rb def survey_params params.require(:survey).permit(:name, :questions_attributes => [:id, :name]) end getter,这看起来有点像kludge但不是太糟糕(有标准的方法吗?):

surveys/edit.html.erb

到目前为止,这么好。问题是:

再次来自Railscast,我在surveys/edit.html.erb <%= f.fields_for :questions do |builder| %> <%= render 'edit_question_fields', f: builder %> <% end %>

中有这个
{ "survey" => { "name" => "Howard", questions_attributes => { "id" => "1", "name" => "Vince" }}}

但是,这将返回以下形式的哈希:

ActiveRecord::StatementInvalid (Could not find table '')

Rails给我一个错误:Questions - 大概是因为没有nested_attributes表(它是一个抽象类)。

那么,我该如何解决呢?在不放弃Question或完全继承的情况下,我可以想到四种方式:

  1. 切换到STI(而不是_type是抽象类),在params散列中包含Survey字段,然后从那里开始。
  2. Survey.rb has_many :basic_questions accepts_nested_attributes_for :basic_questions has_many :multiple_choice_questions accepts_nested_attributes_for :multiple_choice_questions def questions # same as before, still comes in handy end surveys/edit.html.erb <% @survey.questions.each do |question| %> <%= f.fields_for question do |builder| %> <%= render 'edit_question_fields', f: builder %> <% end %> <% end %>` 分别处理每种问题类型:

    { "survey" => { "name" => "Howard", "basic_question" => { "id" => "1", "name" => "Vince" }, "multiple_choice_question" => { "id" => "1", "name" => "Naboo" }}}
    

    这几乎可行,但现在我的哈希看起来像这样:

    "basic_questions_attributes"

    我需要索引的问题,例如"basic_question"而不是questions_attributes= - 有人知道怎么做吗?

  3. 覆盖Survey.rb中的QuestionsFormBuilder以对其进行排序。

  4. 创建一个新的Question对象来处理所有内容,与“Rails nested attributes form for polymorphic/single table inheritance associations”一致。
  5. 显然,主要关注的是能够以最少的麻烦在以后放入新的Question子类(或改变现有子类的行为)。

    目前我倾向于使用选项#3,因为它看起来最简单,最优雅,但是,我不确定我是不是错过了一些更好的方法来做到这一点。 (或以某种方式搞砸了{{1}}子类化实现。)有没有人有更好的想法或更多类似Rails的方法来实现这一点?!

1 个答案:

答案 0 :(得分:1)

看一下使用表单对象来封装逻辑和创建问题? http://railscasts.com/episodes/416-form-objects

我还会考虑使用STI,以便您的Survey.rb不需要重新定义问题