What is the equivalent of the has_many 'conditions' option in Rails 4?

Solution 1:

Needs to be the second arg:

class Customer < ActiveRecord::Base
  has_many :orders, -> { where processed: true }
end

http://edgeguides.rubyonrails.org/association_basics.html#scopes-for-has-many

RESPONSE TO UPDATE:

Put the order inside the block:

has_many :friends, -> { where(friendship: {status: 'accepted'}).order('first_name DESC') }, :through => :friendships

Solution 2:

While other answers on here are technically correct, they violate encapsulation. The User model should not know that the Friendship model has a column called status, and that it can have a specific value like accepted.

If you decide to make a change, to take advantage of Enums in Rails 4, for example, you would have to change both User and Friendship models. This could lead to bugs that maintaining encapsulation avoids.

I would expose a scope in the Friendship model:

scope :accepted, -> { where(status: :accepted) }

I would then use this scope in the User model, hiding any implementation details from User.

has_many :friendships, -> { Friendship.accepted }
has_many :friends, through: :friendships

# Or...

has_many :friends, -> { Friendship.accepted }, through: :friendships

You can go further and rename the scope to accepted_friendships to be clearer.

has_many :accepted_friendships, -> { Friendship.accepted }
has_many :friends, through: :accepted_friendships

Now you have successfully encapsulated implementation details in their respective models. Should anything change you only have one place to change it, reducing maintenance and increasing robustness.