Reputation: 160
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
Reputation: 11
I've ended up packaging my solution into a gem for experimental purposes. Feel free to try it.
Upvotes: 1
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