2013-10-24 148 views
3

我需要帮助实现或将其分解为单表继承(STI)。我已经阅读过有关这方面的内容,但如果我以正确的方式开展工作,我还不太确定。如果你们有建议来实施它。或者,即使它与我现在有很大不同,请咨询。STI帮助。需要帮助重构我现有的代码

所以,通常我有以下类(所有模型)。

class Article < ActiveRecord::Base 
    has_many :attachments 

    has_many :medias 
    has_one :banner 

    accepts_nested_attributes :medias 
    ... 
end 

class Attachment < ActiveRecord::Base 
    belongs_to :article 
end 

class Media < Attachment 
    default_scope { where(attachment_type: 'media') } 

    def audio?; media_type == 'audio'; end 
    def video?; media_type == 'video'; end 

    validate :embed_url, presence: true if :video? 

    def path 
    if audio? 
     # Different audio path 
    elsif video? 
     # Different video path 
    end 
    end 

    after_commit :process_audio_file 
    def process_audio_file; ...; end 

    after_commit :process_video_file 
    def process_video_file; ...; end 
end 

class Banner < Attachment 
    default_scope { where(attachment_type: 'banner') } 
    ... 
end 

,通常它会正常工作太..

article = Article.first 
first_media = article.medias.first 
banner = article.banner 

但后来我发现,Media可能会是臃肿,有不同的东西太多不同的逻辑不同的media_types做。所以我试图通过这样做来区分它们:

class Article < ActiveRecord::Base 
    has_many :attachments 

    has_many :medias 
    has_one :banner 

    accepts_nested_attributes_for :medias 
end 

class Attachment < ActiveRecord::Base 
    belongs_to :article 
end 

class Media < Attachment 
    default_scope { where(attachment_type: 'media') } 
end 

class AudioMedia < Media 
    default_scope { where(media_type: 'audio') } 

    def path 
    # Audio path 
    end 

    after_commit :process_audio_file 
    def process_audio_file; ...; end 
end 

class VideoMedia < Media 
    default_scope { where(media_type: 'video') } 

    validate :embed_url, presence: true 

    def path 
    # Video path 
    end 

    after_commit :process_video_file 
    def process_video_file; ...; end 
end 

现在我在这里将逻辑彼此分开。大!但现在它带来像几个问题:

article = Article.first 
first_media = article.medias.first 

在这样做,我只是我在Media类......为了让说AudioMedia类,我要做的是:

"#{first_media.media_type}Media".constantize.find(first_media.id) 

此外,为了使我的nested_attributes能够正常工作,我必须定义

accepts_nested_attributes_for :audio_medias 
accepts_nested_attributes_for :video_medias 

使其工作正确吗?然后我不得不定义他们的关系,就像:

has_many :medias 
has_many :audio_medias 
has_many :video_medias 

有什么建议吗?谢谢,欢呼!

编辑

添加相关的表和字段

articles 
    id 
    [some_other_fields] 

attachments 
    id 
    article_id 
    attachment_type # media, banner, etc... 
    media_type # audio, video, etc... 
    [some_other_fields] 
+1

附件表中是否有'type'列? STI需要这个来确定单个记录的类别 –

+0

@MarkMeeus类型是什么意思?我为“文章”和“附件”添加了表格和字段。 – index

+0

我在下面发布了一个答案... –

回答

0

,你可以请添加您的迁移?

通常情况下,我希望是这样的:

article.medias.first.class == AudioMedia #true 

,并有一个原因把媒体类的地方吗?只是为了进行默认范围,这不是必需的,因为您有一个分开的Class AudioMedia或VideoMedia,它位于类型为AudioMedia或VideoMedia的附件中。你可以很容易地通过他们的类名访问它们。

顺便说一句,你应该看看paperclip或carrier_wave。

+0

是的。通常它会像'article.medias.first'那样在最上面提到,它通常是'Media'。但我想根据STI的建议分开它们的逻辑。 “媒体”也用于包含任何媒体的常用方法和其他方法。 – index

0

看起来你错过了一些与STI相关的重要信息。 当你创建一个新的AR实例并且你的表有一个名为'type'的列时,AR会在你的列中存储你的对象的类名。 稍后选择记录时,AR将使用类型列中的值来检测要构造它的类。

它看起来像你在某种程度上通过使用这些示波器和音频实现类似的东西?视频?方法。

所以第一

rails g migration add_type_to_attachments type:string 
rake db:migrate 

然后让你的代码看起来是这样的:

class Article < ActiveRecord::Base 
    has_many :attachments  
    accepts_nested_attributes_for :attachments 
end 

class Attachment < ActiveRecord::Base 
    belongs_to :article 
end 

class Media < Attachment 

end 

class AudioMedia < Media 

    def path 
    # Audio path 
    end 

    after_commit :process_audio_file 
    def process_audio_file; ...; end 
end 

class VideoMedia < Media   
    validate :embed_url, presence: true 

    def path 
    # Video path 
    end 

    after_commit :process_video_file 
    def process_video_file; ...; end 
end  

现在所有的附件都在一个场

article.attachments 

如果您只需要例如视频

article.attachments.select{|a|a.is_a? VideoMedia} 
+0

有没有在轨道内置这个?我似乎无法找到它。你能为这个文件提供一个链接,这样我可以进一步阅读吗?另外,如果我这样做,并做了'article.attachments.select {| a | a.is_a? VideoMedia}'我还需要做一个'VideoMedia.find(#)'才能找到实际的模型?或者我怎样才能得到它? – index