Dom
Dom

Reputation: 160

Aliasing names of polymorphic associations

I'm trying to implement a polymorphic association in a project for the first time but I'm not a fan of how the associations read and was wondering if there's a way of aliasing them?

Example:

# app/models/comment.rb
class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true
end

# app/models/post.rb
class Post < ActiveRecord::Base
  has_many :comments, :as => :commentable
end

# app/models/picture.rb
class Picture < ActiveRecord::Base
  has_many :comments, :as => :commentable
end

Let's say I wanted to retrieve a Post instance from a given Comment, terrific_post = Comment.first.commentable just doesn't read well in my opinion. Is there a way to alias different association names in the Comment model and avoid relying on a single name such as commentable? I realize you could choose a name which aligns better to your specific dsl rather than say "commentable", however I'd prefer to continue referring to associations with names (or variations) based on their relationships, similar to Comment.first.post and `Comment.first.picture' if at all possible.

At the end of the day it's not a big sacrifice for the flexibility you get with polymorphic associations. Just curious if a solution exists.

Note: the following example was taken from The Odin Project which does a great job explaining various types of associations.

Upvotes: 2

Views: 2756

Answers (2)

mansakondo
mansakondo

Reputation: 11

I've ended up packaging my solution into a gem for experimental purposes. Feel free to try it.

Upvotes: 1

Oleksandr Avoiants
Oleksandr Avoiants

Reputation: 1929

You can alias an association like any other method:

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true
  alias_method :post, :commentable
  alias_method :picture, :commentable
end

And you can then do Comment.first.post and Comment.first.picture.

But Comment.first.post can be either a Post or a Picture, so you should know what are you doing.

Another approach would be implement methods that return post only if commentable is a Post and picture only when commentable is a Picture:

class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true

  def post
    commentable if commentable.is_a? Post
  end

  def picture
    commentable if commentable.is_a? Picture
  end
end

Upvotes: 2

Related Questions