web-dev-qa-db-fra.com

ActiveRecord OR requête

Comment faire une requête OR dans Rails 3 ActiveRecord. Tous les exemples que je trouve ont juste ET des requêtes.

Edit: La méthode _ ou _ est disponible depuis Rails 5. Voir ActiveRecord :: QueryMethods

176
pho3nixf1re

Utilisez ARel

t = Post.arel_table

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

Le SQL résultant:

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

Si vous souhaitez utiliser un opérateur OR sur la valeur d'une colonne, vous pouvez transmettre un tableau à .where et ActiveRecord utilisera IN(value,other_value):

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

les sorties:

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

Cela devrait atteindre l'équivalent d'un OR sur une seule colonne

202
deadkarma

dans Rails 3, il devrait être

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

Cela inclut également le sql brut, mais je ne pense pas qu’il existe un moyen dans ActiveRecord de procéder à une opération OR. Votre question n'est pas une question de noob.

148
rubyprince

Une version mise à jour de Rails/ActiveRecord peut prendre en charge cette syntaxe de manière native. Cela ressemblerait à:

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

Comme indiqué dans cette demande d'extraction https://github.com/Rails/rails/pull/9052

Pour l'instant, il suffit de s'en tenir aux travaux suivants:

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

Mise à jour: Selon https://github.com/Rails/rails/pull/16052 la or fonctionnalité sera disponible dans Rails 5

Mise à jour: La fonction a été fusionnée dans la branche Rails 5.

55
Christian Fazzini

Rails a récemment ajouté cela à ActiveRecord. Il semble être publié dans Rails 5. Engagé à maîtriser dé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)
35
Greg Olsen

Rails 5 est livré avec une méthode or. (l encre à la documentation )

Cette méthode accepte un objet ActiveRecord::Relation. par exemple:

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

Si vous souhaitez utiliser des tableaux comme arguments, le code suivant fonctionne dans 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))

Plus d'informations: OU requêtes avec des tableaux comme arguments dans Rails 4 .

14
Rafał Cieślak

Le plugin MetaWhere est complètement incroyable.

Vous pouvez facilement mélanger les OR et les AND, associer des conditions à toute association et même spécifier des 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

Ajoutez simplement un OR dans les conditions

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

Je viens d'extraire ce plugin du travail client qui vous permet de combiner des étendues avec .or., ex. Post.published.or.authored_by(current_user). Squeel (la nouvelle implémentation de MetaSearch) est également génial, mais ne vous permet pas d'étendre la portée OR, de sorte que la logique de requête peut devenir un peu redondante.

3
Woahdae

Vous pourriez le faire comme:

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

ou plus élégant, installez Rails_or gem et procédez comme suit:

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

Avec Rails + arel, une manière plus claire:

# 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

Produit:

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