Як зробити запит АБО у Rails 3 ActiveRecord. Усі приклади, які я знаходжу, просто мають І запити.
Правка: АБО метод доступний з Rails 5. Див. ActiveRecord :: QueryMethods
Post.where(column: 'something').or(Post.where(other: 'else'))
Як зробити запит АБО у Rails 3 ActiveRecord. Усі приклади, які я знаходжу, просто мають І запити.
Правка: АБО метод доступний з Rails 5. Див. ActiveRecord :: QueryMethods
Post.where(column: 'something').or(Post.where(other: 'else'))
Відповіді:
Використовуйте ARel
t = Post.arel_table
results = Post.where(
t[:author].eq("Someone").
or(t[:title].matches("%something%"))
)
Отриманий SQL:
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
буде вироблятися LIKE
для sqlite (регістр нечутливий до замовчування) та ILIKE
для postgres (потрібен явний нечутливий регістр, як оператор).
Якщо ви хочете використовувати оператор АБО для значення одного стовпця, ви можете передати масив .where
і ActiveRecord буде використовувати IN(value,other_value)
:
Model.where(:column => ["value", "other_value"]
Виходи:
SELECT `table_name`.* FROM `table_name` WHERE `table_name`.`column` IN ('value', 'other_value')
Це повинно досягти еквівалента знаку OR
в одному стовпчику
у рейках 3, так і повинно бути
Model.where("column = ? or other_column = ?", value, other_value)
Сюди також входить необроблений sql, але я не думаю, що в ActiveRecord є спосіб зробити АБО операцію. Ваше запитання не є питанням noob.
Page.where("pages.column = ? or pages.other_column = ?", value, other_value)
Оновлена версія Rails / ActiveRecord може підтримувати цей синтаксис спочатку. Це буде схоже на:
Foo.where(foo: 'bar').or.where(bar: 'bar')
Як зазначено в цьому запиті на витяг https://github.com/rails/rails/pull/9052
Наразі просто дотримуватися наступних дій чудово:
Foo.where('foo= ? OR bar= ?', 'bar', 'bar')
Оновлення: По https://github.com/rails/rails/pull/16052or
функція буде доступна в Rails 5
Оновлення: функцію було об’єднано у відділення Rails 5
or
доступно зараз Rails 5, але не реалізовано таким чином, оскільки він очікує, що буде передано 1 аргумент. Він очікує об’єкт Arel. Дивіться прийняту відповідь
or
Метод ActiveRecord працює , якщо ви використовуєте його прямо: а може порушити ваші очікування , якщо він використовується в обсязі , який потім прикутий.
Нещодавно Rails додав це в ActiveRecord. Здається, буде випущено в Rails 5. Зобов’язаний вже освоїти:
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)
Рейки 5 поставляються or
методом. (л чорнило до документації )
Цей метод приймає ActiveRecord::Relation
об’єкт. наприклад:
User.where(first_name: 'James').or(User.where(last_name: 'Scott'))
Якщо ви хочете використовувати масиви як аргументи, наступний код працює в 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))
Додаткова інформація: АБО запити з масивами як аргументами в Rails 4 .
Order.where(query.where_values.inject(:or))
користуватися arel весь шлях.
MetaWhere плагін зовсім дивно.
Легко змішуйте АБО та І, приєднуйтесь до умов будь-якої асоціації та навіть вказуйте ІХ ВАРТІСТЬ!
Post.where({sharing_level: Post::Sharing[:everyone]} | ({sharing_level: Post::Sharing[:friends]} & {user: {followers: current_user} }).joins(:user.outer => :followers.outer}
Просто додайте АБО в умовах
Model.find(:all, :conditions => ["column = ? OR other_column = ?",value, other_value])
Я щойно витягнув цей плагін із роботи з клієнтами, що дозволяє поєднувати сфери застосування .or.
, наприклад. Post.published.or.authored_by(current_user)
. Squeel (новіша реалізація MetaSearch) також чудовий, але не дає вам АБО області застосування, тому логіка запитів може стати трохи зайвою.
З рейки + арел більш чіткий спосіб:
# 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
Виробляє:
$ Message.by_participant(User.first.id).to_sql
=> SELECT `messages`.*
FROM `messages`
WHERE `messages`.`sender_id` = 1
OR `messages`.`recipient_id` = 1
Ви можете це зробити так:
Person.where("name = ? OR age = ?", 'Pearl', 24)
або більш елегантний, встановіть дорогоцінний камінь rails_or і зробіть це так:
Person.where(:name => 'Pearl').or(:age => 24)
Я хотів би додати, що це рішення для пошуку декількох атрибутів ActiveRecord. З тих пір
.where(A: param[:A], B: param[:B])
буде шукати A і B.
Book.where.any_of(Book.where(:author => 'Poe'), Book.where(:author => 'Hemingway')