Rails 5: ActiveRecord OR query

Ruby on-RailsRubyActiverecordRuby on-Rails-5Rails Activerecord

Ruby on-Rails Problem Overview


How do you do an or query in Rails 5 ActiveRecord? Also, is it possible to chain or with where in ActiveRecord queries?

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

The ability to chain or clause along with where clause in ActiveRecord query will be available in Rails 5. See the related discussion and the pull request.

So, you will be able to do the following things in Rails 5:

To get a post with id 1 or 2:

Post.where('id = 1').or(Post.where('id = 2'))

Some other examples:

(A && B) || C:

	Post.where(a).where(b).or(Post.where(c))

(A || B) && C:

	Post.where(a).or(Post.where(b)).where(c)

Solution 2 - Ruby on-Rails

We don't need to wait for rails 5 to use this OR query. We can also used it with rails 4.2.3. There is a backport here.

Thank to Eric-Guo for gem where-or, Now we can add this OR functionality in >= rails 4.2.3 also using this gem.

Solution 3 - Ruby on-Rails

(Just an addition to the answer by K M Rakibul Islam.)

Using scopes, the code can become prettier (depending on the eyes looking):

scope a,      -> { where(a) }
scope b,      -> { where(b) }

scope a_or_b, -> { a.or(b) }

Solution 4 - Ruby on-Rails

I needed to do a (A && B) || (C && D) || (E && F)

But in Rails 5.1.4's current state this get's too complicated to accomplish with the Arel or-chain. But I still wanted to use Rails to generate as much of the query as possible.

So I made a small hack:

In my model I created a private method called sql_where:

private
  def self.sql_where(*args)
    sql = self.unscoped.where(*args).to_sql
    match = sql.match(/WHERE\s(.*)$/)
    "(#{match[1]})"
  end

Next in my scope I created an array to hold the OR's

scope :whatever, -> {
  ors = []

  ors << sql_where(A, B)
  ors << sql_where(C, D)
  ors << sql_where(E, F)

  # Now just combine the stumps:
  where(ors.join(' OR '))
}

Which will produce the expected query result: SELECT * FROM `models` WHERE ((A AND B) OR (C AND D) OR (E AND F)).

And now I can easily combine this with other scopes etc. without any wrongful OR's.

The beauty being that my sql_where takes normal where-clause arguments: sql_where(name: 'John', role: 'admin') will generate (name = 'John' AND role = 'admin').

Solution 5 - Ruby on-Rails

Rails 5 has ability for or clause with where. For Example.

User.where(name: "abc").or(User.where(name: "abcd"))
Recommended Rails Activerecord Solutions

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionK M Rakibul IslamView Question on Stackoverflow
Solution 1 - Ruby on-RailsK M Rakibul IslamView Answer on Stackoverflow
Solution 2 - Ruby on-RailsDipak GuptaView Answer on Stackoverflow
Solution 3 - Ruby on-RailsNicholasView Answer on Stackoverflow
Solution 4 - Ruby on-RailsmtrolleView Answer on Stackoverflow
Solution 5 - Ruby on-RailsForamView Answer on Stackoverflow