Создание активных условий записи в массиве - частный метод «сканирование» называется ошибкой
Вопрос
Я пытаюсь построить набор условий динамически, используя массив, как предложено в первом ответе здесь: Один или несколько параметров в модели найдите условия с Ruby On Rails. Анкет Однако я, кажется, делаю что -то неправильно, и я не уверен, что то, что я пытаюсь, принципиально необоснованно или я просто понял свой синтаксис.
Я упрощаюсь до одного условия здесь, чтобы попытаться проиллюстрировать эту проблему, поскольку я пытался создать простое доказательство концепции по этим направлениям, прежде чем уловить на 5 различных стилях состояния, с которыми я сталкиваюсь.
Это работает:
excluded.push 12
excluded.push 30
@allsites = Site.all(:conditions => ["id not in (?)", excluded])
Это приводит к частному методу «сканирование», называемое ошибкой:
conditionsSet = []
excluded.push 12
excluded.push 30
conditionsSet << ["id not in (?)", excluded]
@allsites = Site.all(:conditions => conditionsSet)
Спасибо за совет. Я не был уверен, что правильная вещь заключалась в том, чтобы поместить это в качестве последующего элемента к соответствующему вопросу/ответам, которые я отметил наверху. Так как у меня есть проблема, а не ответ. Если есть лучший способ опубликовать это, связанное с существующим постом, пожалуйста, дайте мне знать.
Решение
Попробуй это:
Рельсы 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
Другие советы
Ты хочешь:
conditionsSet += ["id not in (?)", excluded]
вместо:
conditionsSet << ["id not in (?)", excluded]
+=
добавляет два массива вместе (подумайте об этом как об объединении в один массив), пока <<
Толкает новый элемент на массив. Итак, вы получаете: [["id not in (?)", excluded]]
когда используешь <<
, а также :conditions
хочет массив, где этот первый элемент - строка (не массив).
Пытаться 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
хэш вместо упорядоченных аргументов. По мере того, как ваш проект растет, может появиться больше условий, и вы потеряете то, что происходит. Хэш выглядит и ведет себя более яснее, плюс вы можете легко проверить его, чтобы избежать ошибок программного обеспечения.