Expressive Associations with Rails

Suppose we have a suspiciously simple Rails blogging app with the following models:

class User < ActiveRecord::Base
  has_many  :posts,
            inverse_of: :user

  attr_accessible :name, :email
end
class Post < ActiveRecord::Base
  belongs_to  :user,
              inverse_of: :posts

  attr_accessible :body, :title
end

This done, we could issue:

new_user = User.create
new_post = user.posts.create

Then, when we call new_post.user, we are returned new_user. Great! Well…actually this is OK, but the association could be more explicit about the relationship between Users and Posts. Rails associations allow us to define custom names, like so:

class User < ActiveRecord::Base
  has_many  :posts,
            foreign_key: 'author_id',
            inverse_of: :author

  attr_accessible :name, :email
end
class Post < ActiveRecord::Base
  belongs_to  :author,
              class_name: 'User',
              foreign_key: 'author_id',
              inverse_of: :posts

  attr_accessible :body, :title
end

We’ll also update our database schema, changing the foreign key in posts from user_id to author_id. Then we’ll rake db:rollback db:migrate. Now, when we perform the same setup:

new_user = User.create
new_post = user.posts.create

We can call new_post.author and be returned new_user. The change is relatively minor, but our code is now easier to comprehend. A new contributor can read the statement new_post.author and immediately grasp the intention behind our implementation. Clear, expressive code is easier to read, easier to communicate, and easier to maintain. Awesome!

comments powered by Disqus