Module: ActiveRecord::QueryMethods

Defined in:
lib/by2/ext/active_record.rb

Defined Under Namespace

Classes: OrChain

Instance Method Summary collapse

Instance Method Details

#or(opts = :chain, *rest) ⇒ Object

Returns a new relation, which is the result of filtering the current relation according to the conditions in the arguments, joining WHERE clauses with OR operand, contrary to the default behaviour that uses AND.

#or accepts conditions in one of several formats. In the examples below, the resulting SQL is given as an illustration; the actual query generated may be different depending on the database adapter.

without arguments

If #or is used without arguments, it returns an ActiveRecord::OrChain object that can be used to chain queries with any other relation method, like where:

Post.where("id = 1").or.where("id = 2")
# SELECT `posts`.* FROM `posts`  WHERE (('id = 1' OR 'id = 2'))

It can also be chained with a named scope:

Post.where("id = 1").or.containing_the_letter_a
# SELECT `posts`.* FROM `posts`  WHERE (('id = 1' OR 'body LIKE \\'%a%\\''))

ActiveRecord::Relation

When #or is used with an ActiveRecord::Relation as an argument, it merges the two relations, with the exception of the WHERE clauses, that are joined using the OR operand.

Post.where("id = 1").or(Post.where("id = 2"))
# SELECT `posts`.* FROM `posts`  WHERE (('id = 1' OR 'id = 2'))

anything you would pass to #where

#or also accepts anything that could be passed to the #where method, as a shortcut:

Post.where("id = 1").or("id = ?", 2)
# SELECT `posts`.* FROM `posts`  WHERE (('id = 1' OR 'id = 2'))


69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/by2/ext/active_record.rb', line 69

def or(opts = :chain, *rest)
  if opts == :chain
    OrChain.new(self)
  else
    left = with_default_scope
    right = (ActiveRecord::Relation === opts) ? opts : klass.unscoped.where(opts, rest)

    unless left.where_values.empty? || right.where_values.empty?
      left.where_values = [left.where_ast.or(right.where_ast)]
      right.where_values = []
    end

    left = left.merge(right)
  end
end

#where_astObject

Returns an Arel AST containing only where_values



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/by2/ext/active_record.rb', line 87

def where_ast
  arel_wheres = []

  where_values.each do |where|
    arel_wheres << (String === where ? Arel.sql(where) : where)
  end

  return Arel::Nodes::And.new(arel_wheres) if arel_wheres.length >= 2

  if Arel::Nodes::SqlLiteral === arel_wheres.first
    Arel::Nodes::Grouping.new(arel_wheres.first)
  else
    arel_wheres.first
  end
end