I have an Article
model that can have many different types of content blocks. So an Article
can have many HeadingBlocks
and ParagraphBlocks
like this:
class Article < ApplicationRecord
has_many :heading_blocks
has_many :paragraph_blocks
end
class HeadingBlock < ApplicationRecord
belongs_to :article
end
class ParagraphBlock < ApplicationRecord
belongs_to :article
end
I want to be able to alias both HeadingBlock
and ParagraphBlock
with the same name (blocks
) so if I have an instance of an article, I can do something like this:
@article.blocks // returns all heading blocks and paragraph blocks associated
Is this possible in Rails? If so, could you please provide an example on how to alias multiple models in a has many association using the same name?
Thank you.
CodePudding user response:
You can have a method that returns an array of blocks:
class Article < ApplicationRecord
has_many :heading_blocks
has_many :paragraph_blocks
# NOTE: returns an array of heading and paragraph blocks
def blocks
heading_blocks paragraph_blocks
end
end
You can reorganize the relationships to have a polymorphic association:
class Article < ApplicationRecord
has_many :blocks
end
# NOTE: to add polymorphic relationship add this in your migration:
# t.references :blockable, polymorphic: true
class Block < ApplicationRecord
belongs_to :article
belongs_to :blockable, polymorphic: true
end
class HeadingBlock < ApplicationRecord
has_one :block, as: :blockable
end
class ParagraphBlock < ApplicationRecord
has_one :block, as: :blockable
end
If you can merge HeadingBlock and ParagraphBlock into one database table:
class Article < ApplicationRecord
has_many :blocks
end
# id
# article_id
# type
class Block < ApplicationRecord
belongs_to :article
# set type as needed to `:headding` or `:paragraph`
end
# NOTE: I'd avoid STI; but this does set `type` column automatically to `ParagraphBlock`
# class ParagraphBlock < Block
# end