ActiveRecord Aliasing

Nisa Kusumo
3 min readAug 3, 2021

ActiveRecord is an object relational mapping (ORM) framework used in Rails. When setting up a relational database using ActiveRecord, setting up associations correctly is very important in order to save a lot of headache. The associations describe the relationships between models. This is done in the model definition using belongs_to, has_many and has_many :through. In my limited experience with Ruby and Rails, most of the domain models I worked with were relatively simple — something like one-to-many or many-to-many. Once I started to try to implement a project idea, however, I quickly realized that often times two models are related in multiple ways. This is an example of where aliasing can come in handy.

This blog will use Twitter as an example of a domain model where aliasing could be useful. The models I’ll use for this example are User, Tweet, Like, Comment and Retweet.

These are the associations we’re going to set up:

  • A user has many tweets
  • A user has many likes
  • A user has many liked tweets (tweets through likes)
  • A user has many comments
  • A user has many tweets they’ve commented on (tweets through comments)
  • A user has many retweets
  • A user has many retweeted tweets (tweets through retweets)

For the purpose of this blog we’ll just focus on the User model. We’ll start with the obvious association — a user has many tweets (tweets they wrote). This association is established using has_many as shown below.

class User < ActiveRecord::Base
has_many :tweets
end

A user will also have many likes, comments and retweets.

class User < ActiveRecord::Base
has_many :tweets
has_many :likes
has_many :comments
has_many :retweets
end

But what if I want to be able to see what tweet is associated with each like, comment and retweet? Can we set up has_many :through associations?

class User < ActiveRecord::Base
has_many :tweets
has_many :likes
has_many :tweets, through: :likes
has_many :comments
has_many :tweets, through: :comments
has_many :retweets
has_many :tweets, through: :retweets
end

You can probably see the problem here. If we were to call user.tweets we would only be able to see the tweets the user tweeted. We would have to do extra work if we wanted to see all the tweets that a user liked, commented or retweeted. This is where aliasing comes in. We can set up references to the Tweet model differently when we are calling it through different models.

class User < ActiveRecord::Base
has_many :tweets
has_many :likes
has_many :liked_tweets, through: :likes, source: :tweet
has_many :comments
has_many :commented_tweets, through: :comments, source: :tweet
has_many :retweets
has_many :retweeted_tweets, through: :retweets, source: :tweet
end

To me, this is the clearest way way to set up aliases. Now if you want to access all the tweets a user has liked, you can call user.liked_tweets or user.commented_tweets for all the tweets a user has commented on.

Another way would be to set up aliases in the other classes. For example, in the Comment class, you could add belongs_to :commenter, :class_name => "User", :foreign_key => "user_id" and belongs_to :commented_tweet, :class_name "Tweet", :foreign_key => "tweet_id". Then, in the User class, you could add has_many :comments and has_many :commenters, through: :comments. Both ways have the same outcome so it really just comes down to preference. Aliasing can help make your code more readable/understandable, as well as help set up associations to make accessing data easier.

--

--