1

I have a class that represents a game (match) with 2 scopes:

  scope :home_lineuped, ->() { includes(:home_lineup).where(home_lineup: {lineuped: true }) }
  scope :away_lineuped, ->() { includes(:away_lineup).where(away_lineup: {lineuped: true }) }

I would like to create a new scope with the logical operator Not And on the results, is it possible?

EDIT: What do I mean?

Imagine that: Match.All gives me matches with ID, 1, 2, 3, 4, 5 and 6;

Match.home_lineuped gives me matches with ID, 1, 2 and 6;

Match.away_lineuped gives me matches with ID 3, 4 and 6;

The result of: (Match.home_lineuped AND Match.away_lineuped) is: 6.

Therefore: Not (Match.home_lineuped AND Match.away_lineuped) will result in matches with ID: 1, 2, 3, 4, and 5.

End EDIT

Best Regards,

David

David Sousa
  • 71
  • 10

3 Answers3

1

Depending on the version of Rails you are using ActiveRecord does have a not method. Hope that helps.

John
  • 1,530
  • 1
  • 10
  • 19
1

Your meaning are Match.home_lineuped & Match.away_lineuped and Match.all - (Match.home_lineuped & Match.away_lineuped).

Or create new scope

scope :home_lineuped_and_away_lineuped, ->() { includes(:home_lineup, :away_lineup).where(home_lineups: {lineuped: true }, away_lineups: {lineuped: true }) }

scope :not_home_lineuped_and_away_lineuped, ->() { includes(:home_lineup, :away_lineup).where.not(home_lineups: {lineuped: true }, away_lineups: {lineuped: true }) }

Thuy Nguyen
  • 342
  • 2
  • 8
  • `scope` is just syntactic sugar for declaring class methods. If your method does not fit in a one liner lambda then use normal class method definition for readability. Multi-line scopes are a code smell. – max Jan 01 '20 at 16:55
1
scope :home_lineuped, -> { includes(:home_lineup).where(home_lineup: {lineuped: true }) }
scope :away_lineuped, -> { includes(:away_lineup).where(away_lineup: {lineuped: true }) }

You can call one scope after other for AND logic like this:

Match.home_lineuped.away_lineuped

But if you need scope, you can unite two scopes as:

scope :home_and_lineuped, -> do
  includes(:home_lineup, :away_lineup).
    where(home_lineup: {lineuped: true }, away_lineup: {lineuped: true })
end

And for opposite logic (NOT AND) you can use not:

scope :no_home_away_lineuped, -> do
  includes(:home_lineup, :away_lineup).
    where.not(home_lineup: {lineuped: true }, away_lineup: {lineuped: true })
end
mechnicov
  • 12,025
  • 4
  • 33
  • 56