author avatar

ayushsrivastava

Tue May 21 2024

Scoped associations

Let's say we have two models: User and Post. And we want to get all posts for user. We can do this:

class User < ActiveRecord::Base
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to :user
end

user = User.first
user.posts

But what if we don't ever want to include posts for user which are published? Often I see people doing this:

class User < ActiveRecord::Base
  has_many :posts
end

class Post < ActiveRecord::Base
  belongs_to :user

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

user = User.first
user.posts.published

And this is fine, but you can somehow forget to add published scope to your query. And then you will get all posts, even unpublished. And this is not what you want. Some people use default_scope for this, but it is not good idea. So what we can do? We can use scope in association:

class User < ActiveRecord::Base
  has_many :posts, -> { published }
  has_many :not_published_posts, -> { not_published }
end

class Post < ActiveRecord::Base
  belongs_to :user

  scope :published, -> { where(published: true) }
  scope :not_published, -> { where(published: false) }
end

user = User.first
user.posts # only published posts here

#rails #database #model #associations