DEV Community

Cover image for Understanding The Magic of ActiveRecord
Zil Norvilis
Zil Norvilis

Posted on • Updated on

Understanding The Magic of ActiveRecord

Database associations are very important to understand, since they are the backbone of any application. In this article I'll try to explain how ActiveRecord does its magic. It is crucial to know that Model (slave) that has belongs_to method in its table has a column that stores ID of the database record (master) it is associated with. The master Model has either has_many or has_one method, and has no column that references anything about the slave.
So it means that, one record of slave Model can point only to one master Model record, since there is only one column on slave's table that stores master's ID. This is very important concept to grasp, because it is the base of all ActiveRecord associations.

Simple Association with has_many & belongs_to

So let's say we have a post written by user. This post is off a slave model and it belongs to an user (master model). Each post user 'Kevin' creates, inside post's database record there will be Kevin's User ID stored. This is a simple 'has_many - belongs_to' association.

#  user.rb
class User < ApplicationRecord
  has_many :posts
end
Enter fullscreen mode Exit fullscreen mode
#  post.rb
class Post < ApplicationRecord
  belongs_to :user
end
Enter fullscreen mode Exit fullscreen mode

Post table needs to have a foreign key pointing to user ID. To achieve this we need to create a migration that updates the existing Post table or create new Post model if we don't have one yet.

to update run this:
rails g migration AddUserToPosts user:references

to create new:
rails g model Post user:references

after this our database should be reflected in our schema file like this (unnecessary lines are omitted):

#  schema.rb
  create_table "posts", force: :cascade do |t|
    ...
    t.index ["user_id"], name: "index_posts_on_user_id"
  end
  ...
  add_foreign_key "posts", "users"
Enter fullscreen mode Exit fullscreen mode

has_many :through Association

But what if we want this post to have multiple users? We cannot store multiple user IDs in the post record since there is only one column for that. In such cases we have to use 'many-to-many' association. For this to work we need a middle Model. We can call it anyway we want, but the convenience would be to call it like this 'UserPost'.
Inside this model's table we need to have User ID and Post ID that we want to associate with each other.
So now when user 'Kevin' creates a post, record inside 'user_posts' table would be created consisting of user ID and post ID. Additional user can be assigned to the same post by just creating another 'user_posts' record with same post ID and another user's user ID. This way we can assign any number of users to any number of posts.

class Post < ApplicationRecord
  has_many :user_posts
  has_many :authors, through: :user_posts
end

# in between
class UserPost < ApplicationRecord
  belongs_to :post
  belongs_to :user
end

class User < ApplicationRecord
  has_many :user_posts
  has_many :posts, through: :user_posts
end
Enter fullscreen mode Exit fullscreen mode

to create the UserPost' model we just run:
rails g model UserPost user:references post:references

There are much more stuff to know about associations. But the points laid out here are the starting point which is necessary to comprehend before you can feel completely confident with it. Using these you already would be able to create pretty complex app architectures. Good luck and if you got any questions, don't hesitate to leave a comment bellow.

Discussion (0)