Ответ 1
Чтобы сделать ИЛИ в рельсах 3, проверьте MetaWhere. Там есть хорошая railscast: http://railscasts.com/episodes/251-metawhere-metasearch
Я немного застрял в проблеме и нашел свой путь к Arel, который выглядит так, как будто это должно позволить мне делать OR в моих запросах.
В качестве отправной точки мне нужно было преобразовать существующий запрос Rails 3 в Arel и тот, где я столкнулся с проблемами.
Следующая область и запрос работают так, как я ожидал. Он дает мне запросы, связанные с конкретными объявлениями пользователей.
#in the Request class
scope :responder, lambda { |user| joins(:ad).where(:ads => { :user_id => user }) }
Request.responder(303).to_sql
=> "SELECT \"requests\".* FROM \"requests\" INNER JOIN \"ads\" ON \"ads\".\"id\" = \"requests\".\"ad_id\" WHERE (\"ads\".\"user_id\" = 303)"
В соответствии с doco на странице Arel github и Railscast 215 я должен сделать что-то вроде следующего для репликации запроса с помощью Arel
requests = Request.arel_table
ads = Ad.arel_table
where(requests.join(ads).on(ads[:id].eq(requests[:ad_id])))
Это приводит к ошибке
TypeError: Cannot visit Arel::SelectManager
Я могу сделать следующее в консоли, хотя
r = Request.arel_table
a = Ad.arel_table
r.join(a).to_sql
=> "SELECT FROM \"requests\" INNER JOIN \"ads\" "
Итак, похоже, что он формирует запрос SQL, однако, когда вы помещаете это в
Request.where(r.join(a)).to_sql
Я получаю следующее
TypeError: Cannot visit Arel::SelectManager....
Я пробовал делать другие действия Arel внутри где и работает (например)
Request.where(r[:status].eq(nil)).to_sql
=> "SELECT \"requests\".* FROM \"requests\" WHERE (\"requests\".\"status\" IS NULL)"
Это немного выше моих растущих знаний по рулонам/рубинам. Любые идеи?
Спасибо заранее.
Чтобы сделать ИЛИ в рельсах 3, проверьте MetaWhere. Там есть хорошая railscast: http://railscasts.com/episodes/251-metawhere-metasearch
Чем больше ответ здесь, тем более, что, несмотря на причудливый, вдохновляющий пример: http://magicscalingsprinkles.wordpress.com/2010/01/28/why-i-wrote-arel/
... Активная запись фактически не поддерживает полную функциональность Arel. По крайней мере, не через отношения или области. Вы можете создавать любые (большинство) запросов в Arel, но в конце вы будете использовать:
sql = User.arel_table.(something awesome in Arel).to_sql
users = User.find_by_sql(sql)
Технически, все еще существует метод ".to_a", но он не возвращает экземпляры модели ActiveRecord, и он устарел.
{ОБНОВЛЕНИЕ}
http://erniemiller.org/projects/squeel/ - это лучшее, что может случиться с ActiveRecord, когда-либо. Все, что Арель, понял.
Вы можете использовать join_sources.first
на Arel::SelectManager
и передать это, чтобы присоединиться к
requests = Request.arel_table
ads = Ad.arel_table
Request.joins(requests.join(ads).on(ads[:id].eq(requests[:ad_id])).join_sources.first)
Я не эксперт по Arel, но я думаю, что вы хотите объединить соединение и где области, а не включать один в другой. Поэтому вместо
where(requests.join(ads).on(ads[:id].eq(requests[:ad_id])))
попробуйте (например):
requests.join(ads).on(ads[:id].eq(requests[:ad_id])).where(requests[:status].eq(nil))
Наиболее гибкое решение, которое я нашел до сих пор, выглядит примерно так:
class Request
class << self
def your_join_scope
joins('INNER JOIN "ads" ON "ads"."id" = "requests"."ad_id"')
end
end
end
Сила этого заключается в том, что вы можете смешивать и сопоставлять его с другими областями