ti-enxame.com

ActiveRecord OR consulta

Como você faz uma consulta OR no Rails 3 ActiveRecord. Todos os exemplos que eu encontrei apenas têm consultas e.

Edit: OU o método está disponível desde Rails 5. Veja ActiveRecord :: QueryMethods

173
pho3nixf1re

Use ARel

t = Post.arel_table

results = Post.where(
  t[:author].eq("Someone").
  or(t[:title].matches("%something%"))
)

O SQL resultante:

ree-1.8.7-2010.02 > puts Post.where(t[:author].eq("Someone").or(t[:title].matches("%something%"))).to_sql
SELECT     "posts".* FROM       "posts"  WHERE     (("posts"."author" = 'Someone' OR "posts"."title" LIKE '%something%'))
108
Dan McNevin

Se você quiser usar um operador OR no valor de uma coluna, você pode passar uma matriz para .where e o ActiveRecord usará IN(value,other_value):

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

saídas:

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

Isso deve atingir o equivalente a um OR em uma única coluna

198
deadkarma

em Rails 3, deve ser

Model.where("column = ? or other_column = ?", value, other_value)

Isso também inclui sql bruto, mas eu não acho que haja uma maneira em que o ActiveRecord execute OR operação. Sua pergunta não é uma questão noob.

147
rubyprince

Uma versão atualizada do Rails/ActiveRecord pode suportar esta sintaxe nativamente. Seria semelhante a:

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

Como observado neste pedido de pull https://github.com/Rails/rails/pull/9052

Por enquanto, basta seguir as seguintes funções:

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

Atualização: De acordo com https://github.com/Rails/rails/pull/16052 o recurso or estará disponível in Rails 5

Atualização: O recurso foi mesclado com Rails 5 branch

55
Christian Fazzini

Rails recentemente adicionou isso no ActiveRecord. Parece ser lançado em Rails 5. Comprometido a dominar já:

https://github.com/Rails/rails/commit/9e42cf019f2417473e7dcbfcb885709fa2709f89

Post.where(column: 'something').or(Post.where(other: 'else'))

# => SELECT * FROM posts WHERE (column = 'something') OR (other = 'else)
34
Greg Olsen

O Rails 5 vem com um método or. (l tinta para documentação )

Este método aceita um objeto ActiveRecord::Relation. por exemplo:

User.where(first_name: 'James').or(User.where(last_name: 'Scott'))
17
Santhosh

Se você quiser usar arrays como argumentos, o seguinte código funciona em 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))

Mais informações: OU consultas com arrays como argumentos em Rails 4 .

14
Rafał Cieślak

O plugin MetaWhere é completamente incrível.

Misture facilmente ORs e ANDs, junte condições em qualquer associação e até mesmo especifique OUTER JOIN!

Post.where({sharing_level: Post::Sharing[:everyone]} | ({sharing_level: Post::Sharing[:friends]} & {user: {followers: current_user} }).joins(:user.outer => :followers.outer}
7
Duke

Basta adicionar um OR nas condições

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

Acabei de extrair este plugin do trabalho do cliente que permite combinar escopos com .or., ex. Post.published.or.authored_by(current_user). Squeel (implementação mais recente do MetaSearch) também é excelente, mas não permite escopos OR, portanto, a lógica de consulta pode ficar um pouco redundante.

3
Woahdae

Você poderia fazer como:

Person.where("name = ? OR age = ?", 'Pearl', 24)

ou mais elegante, instale Rails_or gem e faça como:

Person.where(:name => 'Pearl').or(:age => 24)
3
khiav reoy

Com Rails + arel, um caminho mais claro:

# 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

Produz:

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