Rails where() clause on model association?

Ruby on-Rails

Ruby on-Rails Problem Overview


Suppose I have an Account model which has_many Users. Accounts have a boolean "active" column. How can I get all Users that belong to "active" accounts?

@users_of_active_accounts = User.?

Thanks!

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

Try this:

User.joins(:account).where(:accounts => { :active => true })

Solution 2 - Ruby on-Rails

You need to join the accounts table and merge appropriate Account scope:

User.joins(:account).merge(Account.where(:active => true))

Solution 3 - Ruby on-Rails

Use a where clause in the Account model's association:

class Account < ActiveRecord::Base
  has_many :users, -> {where(active: true)}

The other queries will work, but if you only always care about active users, filtering at the association level will properly encapsulate the filter and save you headaches in the future.

Update:

You can also specify 2 relations on the same table:

 class Account < ActiveRecord::Base
   has_many :users
   has_many :active_users, -> {where(active: true)}, :class_name => 'User'

2nd Update:

After re-reading the question, I now see that my answer didn't answer the question. Here's my answer to the question:

User.where(account: Account.where(active: true))

3rd Update: Here's an example User model that has an active_users attribute

class User < ActiveRecord::Base
  belongs_to :account
  def self.active
    where(account: Account.where(active: true))
  end
end

Doing it this way allows you to put it inline with other user queries:

User.active.where(created_at: (1.week.ago..0.day.ago)).count

Solution 4 - Ruby on-Rails

Try this:

Account.includes(:users).where(active: true)

Solution 5 - Ruby on-Rails

A gem that exists to do that: activerecord_where_assoc (I'm the author)

With it, you can do what you want this way:

@users_of_active_accounts = User.where_assoc_exists(:account, active: true)

And if you have a scope on Account for active, you could call it this way:

@users_of_active_accounts = User.where_assoc_exists(:account, &:active)

So now, if you want, you can make a nice scope for this:

class User < ActiveRecord::Base
  belongs_to :account
  
  scope :active_account, -> { where_assoc_exists(:account, active: true) }
end

@users_of_active_accounts = User.active_account

Read more in the documentation. Here is an introduction and examples.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDerek JView Question on Stackoverflow
Solution 1 - Ruby on-RailsDogbertView Answer on Stackoverflow
Solution 2 - Ruby on-RailsSimon PerepelitsaView Answer on Stackoverflow
Solution 3 - Ruby on-RailsJared MenardView Answer on Stackoverflow
Solution 4 - Ruby on-RailsNickolay EfimovView Answer on Stackoverflow
Solution 5 - Ruby on-RailsMaxime LapointeView Answer on Stackoverflow