I need help implementing or breaking this into Single-Table-Inheritance (STI). I have read about it and I'm not quite sure yet if I'm going about this the right way. If you guys have suggestions to implement it. Or even if it's very different from what I have now, please advice.
So, normally I have this following classes (all models).
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
And typically it would work normally too..
article = Article.first
first_media = article.medias.first
banner = article.banner
But then I noticed that Media
would probably be bloated and have too many different logics with different things to do for different media_types. So I tried to separate them by doing this:
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
Now here I have separated logic from each other. Great! But now it poses few problems like:
article = Article.first
first_media = article.medias.first
In doing this, I'm only at Media
class... To get to say AudioMedia
class, what I have to do is:
"#{first_media.media_type}Media".constantize.find(first_media.id)
Also, for my nested_attributes to work, I'd have to define
accepts_nested_attributes_for :audio_medias
accepts_nested_attributes_for :video_medias
to make it work right? Then I'd have to define their relationships as well like:
has_many :medias
has_many :audio_medias
has_many :video_medias
Any advice? Thanks and cheers!
EDIT
Added the related tables and fields
articles
id
[some_other_fields]
attachments
id
article_id
attachment_type # media, banner, etc...
media_type # audio, video, etc...
[some_other_fields]