2016-02-22 51 views
1

如果我有以下型号,它使用STI:如何使用STI创建与现有模型相关的新模型?

# Organization Model 
class Organization < ActiveRecord::Base 
    has_many :questions 
    has_many :answers, :through => :questions 
end 

# Base Question Model 
class Question < ActiveRecord::Base 
    belongs_to :organization 
    has_many :answers 
end 

# Subclass of Question 
class TextQuestion < Question 

end 

# Subclass of Question 
class CheckboxQuestion < Question 

end 

什么是建立一个新对象的Question还涉及Organization特定类型的正确方法是什么?换句话说,如果我有一个组织,并且我希望该组织有一个新的CheckboxQuestion,我可以使用常规构建器方法吗?

例如,我期待能够做到:

org = Organization.last 
org.text_questions.build(:question_text => "What is your name?") 

...但是这给了我一个NoMethodError: undefined method text_questions错误。

回答

3

Organization模型是不知道的类中的从Question继承,因此您可以用这种方式启动/创建问题实例。为了启动/创建特定类型的问题,您必须自己明确设置它。例如:

organization = Organization.where(...).last 
organization.questions.build(question_text: 'text', type: 'TextQuestion') 

您可以定义在Organization类多has_many *_questions,但如果你最终有很多的Question子类应用程序中的感觉就像一个糟糕的设计和事情会变得不可收拾。

+0

那么,在你上面的例子中,手动指定新问题的'type'并不是很差的技术? –

+0

我认为这两种方法都会引入潜在的复杂性/问题(IMO),这是部分人为什么在许多情况下选择避免STI的部分原因。如果有重复的逻辑/代码,您可能会考虑其他选项,如关注(包括关注::问题)等,仅供将来阅读/考虑。 :) –

+0

@GregMatthewCrossley我认为这不是,因为通过不定义基于类型的多个关联,“Organization”对“Question”及其子类所发生的情况了解不多。它只知道'Question'提供的接口,这是一件好事。我认为这是做事最干净的方式,但这只是我的看法。 –

2

不是100%肯定没有看到你的Organization模型,但是这可能是你在找什么:

class Organization < ActiveRecord::Base 
    has_many :test_questions 
    has_many :checkbox_questions 
end 

希望帮助:)

+0

所以如果我理解正确,我需要在'Organization'和'Question'的所有子类之间建立一个'has_many'关系? –

+2

沿着Ioannis提到的观点 - 组织模型现在特别对“TextQuestion”有所了解。您或者需要定义has_many关系,方法,或者在他演示时自己明确定义它。无论哪个对你来说都是最直接的。 –

相关问题