Home > Mobile >  Possible to alias has many associations with the same alias with different models?
Possible to alias has many associations with the same alias with different models?

Time:05-19

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
  • Related