[ruby-on-rails] ActiveRecord O consulta



Answers

Si desea utilizar un operador OR en el valor de una columna, puede pasar una matriz a .where y ActiveRecord usará IN(value,other_value) :

Model.where(:column => ["value", "other_value"]

productos:

SELECT `table_name`.* FROM `table_name` WHERE `table_name`.`column` IN ('value', 'other_value')

Esto debería lograr el equivalente de un OR en una sola columna

Question

¿Cómo se hace una consulta O en Rails 3 ActiveRecord. Todos los ejemplos que encuentro solo tienen consultas AND.

Editar: El método O está disponible desde Rails 5. Ver ActiveRecord::QueryMethods




Solo agregue un quirófano en las condiciones

Model.find(:all, :conditions => ["column = ? OR other_column = ?",value, other_value])



Si desea utilizar matrices como argumentos, el siguiente código funciona en Rails 4:

query = Order.where(uuid: uuids, id: ids)
Order.where(query.where_values.map(&:to_sql).join(" OR "))
#=> Order Load (0.7ms)  SELECT "orders".* FROM "orders" WHERE ("orders"."uuid" IN ('5459eed8350e1b472bfee48375034103', '21313213jkads', '43ujrefdk2384us') OR "orders"."id" IN (2, 3, 4))

Más información: consultas OR con matrices como argumentos en Rails 4 .




Acabo de extraer este complemento del trabajo del cliente que le permite combinar ámbitos con .or. , ex. Post.published.or.authored_by(current_user) . Squeel (implementación más reciente de MetaSearch) también es excelente, pero no te permite O alcances, por lo que la lógica de consulta puede ser un poco redundante.




Una versión actualizada de Rails / ActiveRecord puede admitir esta sintaxis de forma nativa. Se vería similar a:

Foo.where(foo: 'bar').or.where(bar: 'bar')

Como se señala en esta solicitud de extracción https://github.com/rails/rails/pull/9052

Por ahora, simplemente seguir con lo siguiente funciona muy bien:

Foo.where('foo= ? OR bar= ?', 'bar', 'bar')

Actualización: según https://github.com/rails/rails/pull/16052 la función or estará disponible en Rails 5

Actualización: la característica se ha fusionado con la rama Rails 5




Con rails + arel, una forma más clara:

# Table name: messages
#
# sender_id:    integer
# recipient_id: integer
# content:      text

class Message < ActiveRecord::Base
  scope :by_participant, ->(user_id) do
    left  = arel_table[:sender_id].eq(user_id)
    right = arel_table[:recipient_id].eq(user_id)

    where(Arel::Nodes::Or.new(left, right))
  end
end

Produce:

$ Message.by_participant(User.first.id).to_sql 
=> SELECT `messages`.* 
     FROM `messages` 
    WHERE `messages`.`sender_id` = 1 
       OR `messages`.`recipient_id` = 1



Related