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

标签 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 setter/getter 在 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

到现在为止还挺好。问题是这样的:

再次来自 Railscast,我在 surveys/edit.html.erb 中有这个:
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" }}}

Rails 给我一个错误:ActiveRecord::StatementInvalid (Could not find table '') ——
大概是因为没有 Questions表(它是一个抽象类)。

那么,我该如何解决呢?不弃nested_attributes或者完全继承,我能想到四种方式:
  • 切换到 STI(而不是 Question 作为抽象类),包括 _type params 散列中的字段,然后从那里开始。
  • Survey分别处理每种问题类型:
    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=在 Survey.rb 中进行整理。
  • 新建 QuestionsFormBuilder对象来处理一切,沿着“Rails nested attributes form for polymorphic/single table inheritance associations”的路线。

  • 显然,一个主要问题是能够放入新的 Question稍后以最少的麻烦创建子类(或更改现有子类的行为)。

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

    最佳答案

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

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

    关于ruby-on-rails - 如何使用继承和嵌套属性构建 Rails 表单?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20035694/

    相关文章:

    ruby-on-rails - Rails - 包括与动态条件的关联

    mysql - 如果数组为空,where_in codeigniter 错误

    ruby-on-rails - Rails - 根据首字母搜索和排序

    mysql - 如何从 Rails 3 中的 LEFT OUTER JOIN 获取最新记录

    ruby-on-rails - 未定义的方法 `remote_function'

    java - 静态方法继承和多态

    c# - 使用 JSON.NET 序列化时如何将属性从接口(interface)继承到对象

    java - 我不明白为什么这个程序不起作用。多态性

    ruby-on-rails - 更改 Carrierwave 上传路径以适应 Cloud 66 的配置

    ruby-on-rails - session 在 Ruby on Rails 中是如何工作的?