11

Let us say I have an array (received from the client side) of ids:

myArray = [1,5,19,27]

And I would like to return ALL items for which the (secondary) id is in that list.

In SQL this would be:

SELECT * FROM Items WHERE id IN (1,5,19,27)

I am aware that I could do:

Item.where(id: [1,5,9,27]),

however the longer where query that this would be tacked onto uses the prepared statement syntax Item.where('myAttrib = ? AND myOtherAttrib <> ? AND myThirdAttrib = ?', myVal[0], myVa[1], myVal[2])

with that in mind, what I would like is the following:

Item.where('id IN ?', myArray)

However, that produces a syntax error:

ActiveRecord::StatementInvalid: PG::Error: ERROR: syntax error at or near "1" LINE 1: SELECT "items".* FROM "items" WHERE (id in 1,2,3,4)

How can I work around this? What is the right way to use where with the prepared statement syntax for IN expressions.

3 Answers 3

19

I ended up using:

Item.where('id IN (?)', myArray)

Sign up to request clarification or add additional context in comments.

Comments

1

You need to change your query to the following:

Item.where('id = ?', myArray) 

ActiveRecord will then convert this to an IN clause if myArray is, in fact, an array.

3 Comments

I am pretty sure this is no longer the case (in Rails 5). This appears to produce the same issue as described in the O.P. Can you please provide a working example? I may be missing something.
Agree, this appears not to be the case, at least since Rails 4.2.
This gives a PG DatatypeMismatch, gotta use Item.where('id IN (?)', myArray) as mentioned by @Abraham P
1

The issue with using raw sql is that the you loose the automatic namespacing of column names thats provided for free by Rails and AREL.

Using raw sql can start causing issues when combining and merging queries or scopes, or when doing joins.

No need to use raw sql to use IN:

Item.where(:id => myArray) # SELECT * FROM items WHERE id IN (...) 

myArray can either be an array of values or an array of Items, or a single value.

Rails is smart enough to change the SQL to what you mean. Infact, if the array contains nil, the SQL will be SELECT * FROM items WHERE (id IS NULL or id IN (...)). This is clearly superior to using raw SQL which is static and only capable of dealing with a single use case.

If Rails doesn;t provide you with what you need, you can fall back to AREL. For example:

class Item scope :with_category, ->(categories) { where( arel_table[:category].in(categories) ) } scope :filter, ->(a, b, c) { not_b = arel_table[:myOtherAttrib].not_eq(b) where(:myAttrib => a, :myThirdAttrib => c).where(not_b) } end Item.with_category(['small', 'large']).filter(*myVal) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.