Объединить массивы условий в Rails - PullRequest
2 голосов
/ 15 июля 2010

Я использую бета-версию Rails3, гем will_paginate и гем & плагин geokit.

Поскольку плагин geokit-rails, по-видимому, не поддерживает области Rails3 (включая проблему с символом: origin), мне нужно использовать синтаксис .find.

Вместо областей мне нужно объединить два набора критериев в формате массива:

У меня есть условие по умолчанию:

conditions = ["invoices.cancelled = ? AND invoices.paid = ?", false, false]

Мне может понадобиться добавить одно из следующих условий к условию по умолчанию, в зависимости от выбора пользовательского интерфейса:

#aged 0
lambda {["created_at IS NULL OR created_at < ?", Date.today + 30.days]}
#aged 30
lambda {["created_at >= ? AND created_at < ?", Date.today + 30.days, Date.today + 60.days]}
#aged > 90
lamdba {["created_at >= ?", Date.today + 90.days]}

Результирующий запрос напоминает:

@invoices = Invoice.find(
  :all, 
  :conditions => conditions,
  :origin => ll     #current_user's lat/lng pair
  ).paginate(:per_page => @per_page, :page => params[:page])

Вопросы:

  1. Есть ли простой способ объединить эти два массива условий (если я правильно сформулировал)
  2. Хотя это не способствует возникновению проблемы, есть ли СУХОЙ способ создать эти стареющие ведра?
  3. Есть ли способ использовать области Rails3 с плагином geokit-rails, который будет работать?

Спасибо за ваше время.

Ответы [ 2 ]

3 голосов
/ 15 июля 2010

Попробуйте это:

ca =  [["invoices.cancelled = ? AND invoices.paid = ?", false, false]]

ca << ["created_at IS NULL OR created_at < ?", 
                    Date.today + 30.days] if aged == 0

ca << ["created_at >= ? AND created_at < ?", 
                    Date.today + 30.days, Date.today + 60.days] if aged == 30

ca << ["created_at >= ?", Date.today + 90.days] if aged > 30

condition = [ca.map{|c| c[0] }.join(" AND "), *ca.map{|c| c[1..-1] }.flatten]

Редактировать подход 2

Патч Обезьяны класса Array. Создайте файл с именем monkey_patch.rb в каталоге config/initializers.

class Array
  def where(*args)
    sql = args[0]     
    unless (sql.is_a?(String) and sql.present?)
      return self
    end    
    self[0] = self[0].present? ? " #{self[0]} AND #{sql}  " : sql 
    self.concat(args[1..-1])    
  end
end

Теперь вы можете сделать это:

cond = []
cond.where("id = ?", params[id]) if params[id].present?
cond.where("state IN (?)", states) unless states.empty?
User.all(:conditions => cond)
2 голосов
/ 01 февраля 2011

Я думаю, что лучше использовать анонимные области.
Проверьте это здесь: http://railscasts.com/episodes/112-anonymous-scopes

...