Comment faire une requête OR dans Rails 3 ActiveRecord. Tous les exemples que je trouve ont juste des requêtes AND.
Edit: la méthode OR est disponible depuis Rails 5. Voir ActiveRecord :: QueryMethods
Comment faire une requête OR dans Rails 3 ActiveRecord. Tous les exemples que je trouve ont juste des requêtes AND.
Edit: la méthode OR est disponible depuis Rails 5. Voir ActiveRecord :: QueryMethods
Post.where(column: 'something').or(Post.where(other: 'else'))
Réponses:
Utiliser 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%'))
matches
produira LIKE
pour sqlite (insensible à la casse par défaut) et ILIKE
sur postgres (nécessite explicitement insensible à la casse comme opérateur).
Si vous souhaitez utiliser un opérateur OR sur la valeur d'une colonne, vous pouvez passer 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
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 faire une opération OR. Votre question n'est pas une question noob.
Page.where("pages.column = ? or pages.other_column = ?", value, other_value)
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 éléments 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 fonctionnalité a été fusionnée avec la branche Rails 5
or
est disponible maintenant Rails 5 mais pas implémenté de cette façon car il s'attend à ce qu'un argument soit passé. Il attend un objet Arel. Voir la réponse acceptée
or
méthode dans ActiveRecord fonctionne si vous l'utilisez directement: mais peut briser vos attentes si elle est utilisée dans une portée qui est ensuite chaînée.
Rails l'a récemment ajouté dans ActiveRecord. Il semble être publié dans Rails 5. Déjà engagé à maîtriser:
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)
Rails 5 est livré avec une or
méthode. (l encre à la documentation )
Cette méthode accepte un ActiveRecord::Relation
objet. par exemple:
User.where(first_name: 'James').or(User.where(last_name: 'Scott'))
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: Requêtes OR avec des tableaux comme arguments dans Rails 4 .
Order.where(query.where_values.inject(:or))
utiliser arel jusqu'au bout.
Le plugin MetaWhere est complètement incroyable.
Mélangez facilement les OU et les AND, joignez les conditions sur n'importe quelle association et spécifiez même OUTER JOIN!
Post.where({sharing_level: Post::Sharing[:everyone]} | ({sharing_level: Post::Sharing[:friends]} & {user: {followers: current_user} }).joins(:user.outer => :followers.outer}
Ajoutez simplement un OU dans les conditions
Model.find(:all, :conditions => ["column = ? OR other_column = ?",value, other_value])
Vous pouvez le faire comme:
Person.where("name = ? OR age = ?", 'Pearl', 24)
ou plus élégant, installez rails_or gem et faites-le comme:
Person.where(:name => 'Pearl').or(:age => 24)
Je viens d'extraire ce plugin du travail client qui vous permet de combiner des portées avec .or.
, ex. Post.published.or.authored_by(current_user)
. Squeel (implémentation plus récente de MetaSearch) est également géniale, mais ne vous permet pas d'étendues OU, donc la logique de requête peut devenir un peu redondante.
Avec rails + arel, une voie 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
Book.where.any_of(Book.where(:author => 'Poe'), Book.where(:author => 'Hemingway')
Je voudrais ajouter que c'est une solution pour rechercher plusieurs attributs d'un ActiveRecord. Depuis
.where(A: param[:A], B: param[:B])
recherchera A et B.