簡単な調査・アンケートアプリを作ろうとしています。アンケートにはQuestions
; ほとんどの質問は 1 つのコンテンツ フィールド (質問自体) で構成されており、調査回答者はそれに対して自由テキストの回答を記述します。(この議論に関係のないフィールドが他にもいくつかあります。)ただし、ユーザーはMultipleChoiceQuestions
orを作成することもできますLikertQuestions
(たとえば、1 ~ 5 のスケールでの回答)。( の場合、 has_manyなどとMultipleChoiceQuestions
呼ばれる別のモデルがあります)。私が知る限り、ここに私のデザインの選択があります: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) 共有の属性とメソッドでモジュール/ミックスインを使用します。
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
and LikertQuestion
eachを指定しました。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
に思えました。モジュール アプローチを使用すると、 、、およびおそらくその他の便利なことを言うことができなくなります。この状況でRailsホットショットは何をしますか? 私はそれが何であれします。MultipleChoiceQuestion
Questions
survey.questions()
survey.questions.build()
サブクラス化とミックスインの長所と短所について非常に包括的な議論を提供する StackOverflow の投稿はありません。
Ruby 1.9.3 (2.0 に切り替えることも考えています)、Rails 3.2.3 を使用しています。