How can I use a named scope in my model against an array of items?
Asked Answered
I

2

8

I know that I can do a query for recent books based on an array as in

scope :recent_books, lambda {|since_dt| {:conditions=>{:created_at >= since_dt}}}

but how can I do a similar query when I have an array of items, e.g. what if I want to know if there any records that match the dates in an array of [date1, date2, date3, etc.]

I think there must be a collect/inject/select/map y method that'll do it but I am not sure which from reading them.

Ingather answered 16/11, 2011 at 16:32 Comment(0)
G
18

If you pass an array as the value, ActiveRecord is smart enough to compare for inclusion in the array. For example,

Book.where(:author_id => [1, 7, 42])

produces a SQL query with a WHERE clause similar to:

WHERE "author_id" IN (1, 7, 42)

You can take advantage of this in a scope the same way you would set normal conditions:

class Book < ....
  # Rails 3
  scope :by_author, lambda { |author_id| where(:author_id => author_id) }

  # Rails 2
  named_scope :by_author, lambda { |author_id
    { :conditions => {:author_id => author_id} }
  }
end

Then you can pass a single ID or an array of IDs to by_author and it will just work:

Book.by_author([1,7,42])
Gynaeco answered 16/11, 2011 at 16:38 Comment(4)
Although I know the syntax changed a bit from rails2's named_scope, would the lambda approach work ok in rails2? Thx, Michael.Ingather
Yeah. I first used this syntax with Rails 2 myself, including some named scopes that matched against arrays. You'll just have to change the where call to a conditions hash.Gynaeco
@MichaelDurrant I added an example of how you would do it with Rails 2.Gynaeco
@Gynaeco And do you know how to work with a array of tuples like [[1,2],[3,2]]. I need to work with the first and second value of each tuple separately.Erstwhile
T
5

In Rails 4, I can check for the inclusion of a string in an array attribute by using a scope like this:

scope :news, -> { where(:categories => '{news}') }

Or with an argument:

scope :by_category, ->(category) { where(:categories => "{#{category}}") }
Tsana answered 3/11, 2014 at 0:7 Comment(1)
thanks, this helped me a lot. the { } around the {news} makes all the difference. Wasn't familar with that syntax..Barbra

© 2022 - 2024 — McMap. All rights reserved.