Rails 5: ActiveRecord O consulta


¿Cómo hacer una consulta or en Rails 5 ActiveRecord? Además, ¿es posible encadenar or con where en consultas ActiveRecord?

Author: K M Rakibul Islam, 2015-09-24

4 answers

La capacidad de encadenar la cláusula or junto con la cláusula where en la consulta ActiveRecord estará disponible en Rieles 5. Véase la discusión relacionada con y la pull request.

Por Lo tanto, usted será capaz de hacer las siguientes cosas en Rieles 5:

Para obtener un post con id 1 o 2:

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

Algunos otros ejemplos:

(A & & B) / / C:

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

(A / / B) & & C:

    Post.where(a).or(Post.where(b)).where(c)
 178
Author: K M Rakibul Islam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-20 12:41:25

No necesitamos esperar a que rails 5 utilice esta consulta OR. También podemos usarlo con rails 4.2.3. Hay un backport aquí.

Gracias a Eric-Guopara gema donde-o, Ahora podemos agregar esta funcionalidad OR en >= rails 4.2.3 también usando esta gema.

 11
Author: Dipak Gupta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-24 06:11:27

Necesitaba hacer un (A && B) || (C && D) || (E && F)

Pero en el estado actual de Rails 5.1.4 esto es demasiado complicado de lograr con Arel o-chain. Pero todavía quería usar Rails para generar tanto de la consulta como fuera posible.

Así que hice un pequeño hack:

En mi modelo creé un método private llamado sql_where:

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

A continuación, en mi ámbito, creé un array para contener los OR

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 '))
}

Que producirá la consulta esperada resultado: SELECT * FROM `models` WHERE ((A AND B) OR (C AND D) OR (E AND F)).

Y ahora puedo combinar fácilmente esto con otros ámbitos, etc. sin ningún quirófano ilícito.

La belleza es que mi sql_where toma argumentos normales de la cláusula where: sql_where(name: 'John', role: 'admin') generará (name = 'John' AND role = 'admin').

 4
Author: mtrolle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-05 13:21:27

(Solo una adición a la respuesta de Km Rakibul Islam.)

Usando scopes, el código puede volverse más bonito (dependiendo de la mirada de los ojos):

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

scope a_or_b, -> { a.or(b) }
 1
Author: Nicholas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-20 19:51:15