Построение условий активной записи в массиве - частный метод 'scan' называется error - PullRequest
2 голосов
/ 24 марта 2010

Я пытаюсь построить набор условий динамически, используя массив, как было предложено в первом ответе здесь: Один или несколько параметров в модели находят условия с помощью Ruby on Rails . Однако я, кажется, что-то делаю неправильно, и я не уверен, что то, что я пытаюсь сделать, в корне неверно или я просто испортил свой синтаксис.

Я упрощаю здесь до одного условия, чтобы попытаться проиллюстрировать проблему, поскольку я попытался построить простое Доказательство концепции в соответствии с этими линиями, прежде чем разбивать на 5 различных стилей условий, с которыми я борюсь.

Это работает:

excluded.push 12
excluded.push 30
@allsites = Site.all(:conditions => ["id not in (?)", excluded])

Это приводит к закрытому методу scan, называемому error:

conditionsSet = []
excluded.push 12
excluded.push 30
conditionsSet << ["id not in (?)", excluded]
@allsites = Site.all(:conditions => conditionsSet)

Спасибо за любой совет. Я не был уверен, правильно ли было поместить это в качестве дополнительного пункта к связанному вопросу / ответам, которые я отмечал вверху. Поскольку у меня есть проблема, а не ответ. Если есть лучший способ опубликовать это, связанное с существующим сообщением, пожалуйста, дайте мне знать.

Ответы [ 3 ]

5 голосов
/ 25 марта 2010

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

Рельсы 2,3

class Site < ActiveRecord::Base

  def self.build_conditions(ids, name=nil, state=nil)
     cond = []
     cond << send(:sanitize_sql_array, ["id NOT IN (?)", ids]) unless ids.empty?
     cond << send(:sanitize_sql_array, ["name = ? ", name]) unless name
     cond << send(:sanitize_sql_array, ["state = ? ", state]) unless state
     cond.join(" and ")
  end    
end

Теперь где-то в вашем контроллере:

Site.all(:conditions => Site.build_conditions([1,2])) 
Site.all(:conditions => Site.build_conditions(nil, "ABC"))

Рельсы 3

class Site < ActiveRecord::Base          
  def self.exclude_ids_by_name_and_state(ids, name=nil, state=nil)
    result = scoped
    result = result.where("id NOT IN (?)", ids) if ids.present?
    result = result.where(:name => name) if name.present?
    result = result.where(:state => state) if state.present?
    result
  end    
end

Теперь где-то в вашем контроллере:

Site.exclude_ids_by_name_and_state([1,2])).all 
Site.exclude_ids_by_name_and_state(nil, "ABC").all
3 голосов
/ 25 марта 2010

Вы хотите:

conditionsSet += ["id not in (?)", excluded]

вместо:

conditionsSet << ["id not in (?)", excluded]

+= добавляет два массива вместе (представьте, что это объединение двух массивов в один), а << помещает новый элемент в массив. Таким образом, вы получаете: [["id not in (?)", excluded]] при использовании <<, а :conditions хочет массив, где этот первый элемент является строкой (а не массивом).

2 голосов
/ 23 июля 2010

Попробуйте SmartTuple , он разработан специально для подобных случаев.

def self.build_conditions(options = {})
  [
    SmartTuple.new(" AND "),
    (["id NOT IN (?)", ids] if options[:ids].present?),
    ({:name => options[:name]} if options[:name].present?),
    ({:state => options[:state]} if options[:state].present?),
  ].sum.compile
end

...

Site.all(:conditions => Site.build_conditions(:ids => {1,2]))
Site.all(:conditions => Site.build_conditions(:name => "abc", :state => "disabled")

Для меня также предпочтительнее использовать options хеш вместо упорядоченных аргументов. По мере роста вашего проекта могут появиться новые условия, и вы не сможете понять, что из этого выйдет. Хэш выглядит и ведет себя более четко, плюс вы можете легко проверить его, чтобы избежать ошибок программного обеспечения.

...