Reputation: 191
I have model User
and User
has column provider
.
Provider can be google
, facebook
or nil
.
I want to make scope, that will output all users, except users with provider google
and older that some time
.
I tried to do it with two scopes:
scope :not_google_authorised, -> { where(provider: [nil, 'facebook']) }
scope :newest_google, -> { where(provider: 'google').where("created_at < ?", Time.now)}
...
users = User.not_google_authorised
users << User.newest_google
It get right results, but it changed class of users
.
I need that users
will be activerecord relations, not array.
I tried do:
users = User.not_google_authorised
users.merge(User.newest_google)
#or
users.or(User.newest_google)
But it doesn't work for me.
How can i combine this 2 scopes, so users
will be activerecord relations, or how can i write one scope instead their?
I use ruby v3.3.7 and rails v4.1
Upvotes: 1
Views: 2069
Reputation: 14910
One way is to do this, not super optimized but gets the job done.
not_google_auth_ids = User.not_google_authorized.ids
newest_ids = User.newest_google.ids
ids = not_google_auth_ids + newest_ids
users = User.where(id: ids)
Upvotes: 2
Reputation: 9
we can right in a single scope that way:
scope :not_authorised, -> { where("(provider = ? and created_at < ?) or provider != ?",'google', Time.now, 'google' }
Upvotes: 0
Reputation: 29598
ActiveRecord::QueryMethods#or
did not exist until rails 5.
Also the current stable ruby version is 3.0.0
which means you cannot be using 3.3.7
as it does not exist yet (and may never exist).
merge
will combine using AND
(intersection).
So your best bet is to use raw SQL where or Arel
like:
where(
User.arel_table[:provider].eq(nil).or(
User.arel_table[:provider].eq('facebook')
).or(
User.arel_table[:provider].eq('google').and(
User.arel_table[:created_at].lt(Time.now)
)
)
)
This should result in:
SELECT
"users".*
FROM
"users"
WHERE
("users"."provider" IS NULL OR "users"."provider" = 'facebook')
OR ( "users"."provider" = 'google' AND "users"."created_at" < [SOME TIME]
Upvotes: 2