我正在尝试构建一个简单的调查/问卷调查应用程序。调查有Questions
;大多数问题由一个内容字段(问题本身)组成,调查人员将在自由文本回复中对此进行撰写。(还有几个其他领域与本次讨论无关。)但是,用户也可以创建MultipleChoiceQuestions
或LikertQuestions
(例如,1 - 5 级的答案)。(在 的情况下,将MultipleChoiceQuestions
有另一个模型称为has_many )。据我所知,这是我的设计选择:Answer
MultipleChoiceQuestion
Answers
1)从问题继承:
class Question < ActiveRecord::Base
attr_accessible :id, :content
end
class MultipleChoiceQuestion < Question
attr_accessible :type
end
class LikertQuestion < Question
attr_accessible :type, :min, :max, :label_min, label_max
end
2)使用具有共享属性和方法的模块/mixin:
module Question
@content, @id
def method1
end
end
class MultipleChoiceQuestion < ActiveRecord::Base
include Question
end
class LikertQuestion < ActiveRecord::Base
include Question
attr_accessible :type, :min, :max, :label_min, label_max
end
这似乎是一个明确的继承案例,所以我选择了选项 1。从那以后,我无法让它工作。单表继承似乎很简单,所以我在他们的模式中给出MultipleChoiceQuestion
了LikertQuestion
每个。type:string
以下是每个的架构(来自 db/schema.rb):
create_table "questions", :force => true do |t|
t.integer "parent"
t.string "type"
t.string "content"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "survey_id"
end
create_table "multiple_choice_questions", :force => true do |t|
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "type"
end
create_table "likert_questions", :force => true do |t|
t.integer "min"
t.integer "max"
t.string "label_min"
t.string "label_max"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "type"
end
如果我实现上面的选项 1,那么 MultipleChoiceQuestion 和 LikertQuestion 实际上并不包含 schema.rb 中指定的任何唯一字段;相反,它们只有从 Question 继承的字段。查看控制台输出:
1.9.3p392 :001 > Question
=> Question(id: integer, parent: integer, content: string, created_at: datetime, updated_at: datetime, survey_id: integer)
1.9.3p392 :002 > LikertQuestion
=> LikertQuestion(id: integer, parent: integer, content: string, created_at: datetime, updated_at: datetime, survey_id: integer)
1.9.3p392 :003 > MultipleChoiceQuestion
=> MultipleChoiceQuestion(id: integer, parent: integer, content: string, created_at: datetime, updated_at: datetime, survey_id: integer)
1.9.3p392 :004 > LikertQuestion.new(:min => 3)
ActiveRecord::UnknownAttributeError: unknown attribute: min
StackOverflow 上有人说 Question 应该是一个抽象类。但是如果我添加
self.abstract_class = true
到 Question.rb,那么我会得到以下信息:
1.9.3p392 :001 > Question
=> Question(abstract)
1.9.3p392 :002 > LikertQuestion
=> LikertQuestion(id: integer, min: integer, max: integer, label_min: string, label_mid: string, label_max: string, created_at: datetime, updated_at: datetime, type: string)
1.9.3p392 :003 > MultipleChoiceQuestion
=> MultipleChoiceQuestion(id: integer, created_at: datetime, updated_at: datetime, type: string)
1.9.3p392 :004 > LikertQuestion.new(:content => "foo")
ActiveRecord::UnknownAttributeError: unknown attribute: content
LikertQuestion
并仅MultipleChoiceQuestion
显示其唯一字段,并且不从父级继承字段。
1)我在这里错过了什么?不管继承是否是最佳解决方案,我都必须忽略一些显而易见的事情。
2)我应该使用模块方法而不是继承吗?正如我所提到的,继承似乎是一件轻而易举的事:LikertQuestion
而且MultipleChoiceQuestion
确实是Questions
. 如果我使用模块方法,我将失去说出诸如survey.questions()
,之类的东西的能力survey.questions.build()
,并且可能还有其他方便的东西。在这种情况下,Rails 能手会做什么?我会做任何事情。
StackOverflow 上没有任何帖子对子类化与 mixin 的优缺点进行非常全面的讨论。
使用 Ruby 1.9.3(虽然考虑切换到 2.0),Rails 3.2.3。