DEV Community

Dino for Wizard Health

Posted on • Edited on

ActiveRecord associations, scoped

ActiveRecord as a neat trick/ability which a lot of folks are not aware of.

You can pass a block to association, for example:

class Account < ApplicationRecord
 has_many :users, -> { where(admin: true) }
end

class User < ApplicationRecord
 belongs_to :account
end
Enter fullscreen mode Exit fullscreen mode

What makes this even more interesting is that you can have multiple associations to the same model with different name and conditions.

class Account < ApplicationRecord
 has_many :users
 has_many :admin_users, -> { where(admin: true) }, class_name: "User"
end
Enter fullscreen mode Exit fullscreen mode

Calling @account.users will return collection of all users, but calling @account.admin_users will return collection of only admin users.

To make things even more interesting, when creating a new record through the association will comply with the association condition.

@account.admin_users.create(name: "Admin User")
Enter fullscreen mode Exit fullscreen mode

creates a new user with admin set to true.

Since, condition executes in the context of the association object, you can also use scopes.

class Account < ApplicationRecord
  has_many :users
  has_many :admin_users, -> { admins }, class_name: "User"
end

class User < ApplicationRecord
 belongs_to :account

 scope :admins, -> { where(admin: true) }
end

@account.admin_users # Works the same as examples above
Enter fullscreen mode Exit fullscreen mode

This associations will also work for eager loading also, calling
Account.includes(:admin_users) will eager load admin users.

ActiveRecord can accomplish this because associations are built from Relation objects, and you can use Relation syntax to customize them.

Isn't this neat!

Top comments (0)