Rails 3.2 - неопределенный метод `where 'для # <Array: ... - Запрос Model.where ()

ruby-on-rails ruby-on-rails-3 sqlite postgresql

7033 просмотра

2 ответа

159 Репутация автора

Я пытаюсь сравнить поля из данного Headerс другими полями в Alarmмодели. Как вы можете видеть в коде, я фильтрую сигналы тревоги в 3 разных шагах. Первые 2 работают отлично. Однако последний не работает. Он сказал:

undefined method `where' for #<Array:...

Насколько я понимаю .where, это метод класса, который работает с массивом. Почему здесь не работает? Я тоже пробовал и с .find_all_byразными вещами ... но безрезультатно.

@header = Header.find(1)

# Extracts those alarms that are ACTIVE and have something in common with the tittles
@alarmsT = Alarm.activated.where("keyword in (?)", [@header.title_es, @header.title_en, @header.title_en])

# Extracts alarms when Header has at least the same categories as an alarm
@alarmsT = @alarmsT.select do |alarm| 
   @header.category_ids.all?{|c| alarm.category_ids.include? c }
end

// this is the one that does NOT work
# Extract alarms which share the same location as Header.events' town
@alarmsF = [] 
@header.events.each do |e|
    @alarmsF =  @alarmsF + @alarmsT.where("alarms.location LIKE ?", e.town)
end

Любая помощь в определении того, что мне не хватает, очень ценится. Спасибо

Автор: Sergio Nekora Источник Размещён: 16.04.2013 04:15

Ответы (2)


7 плюса

30819 Репутация автора

Решение

В первой строке вы успешно возвращаете ActiveRecordRelationобъект в@alarmsT

# Extracts those alarms that are ACTIVE and have something in common with the tittles
@alarmsT = Alarm.activated.where("keyword in (?)", [@header.title_es, @header.title_en, @header.title_en])

На этом этапе вы можете применить дополнительные .where(...)методы, условия или области действия @alarmsTдля дальнейшего построения выражения ARel и возвращаемых результатов.

Однако затем вы запускаете фильтр для этого отношения, преобразуя @alarmsTего в экземплярArray

# Extracts alarms when Header has at least the same categories as an alarm
@alarmsT = @alarmsT.select do |alarm| 
   @header.category_ids.all?{|c| alarm.category_ids.include? c }
end

Вы больше не можете создавать выражение ARel, поскольку Arrayне знаете ни о методе ARel .where(...), ни о каких-либо Alarmобластях или атрибутах вашей модели. Вот почему в приведенном ниже коде вы получаете сообщение об undefined method 'where' for #<Array:...ошибке - вы вызываете .where()экземпляр Array; метод, который не существует.

@alarmsF = [] 
@header.events.each do |e|
  @alarmsF =  @alarmsF + @alarmsT.where("alarms.location LIKE ?", e.town)
end

Это можно исправить, не выполняя команду select для фильтрации по идентификаторам категорий, а вместо этого используя соединение. Создание такого объединения (чтобы проверить наличие хотя бы подмножества значений в связанной таблице / столбце) довольно подробно описано в местах, которые легко найти через Google и здесь, в StackOverflow.

Автор: deefour Размещён: 16.04.2013 04:31

3 плюса

5133 Репутация автора

Как сказал @Deefour, selectвы собираете данные Arrayвместо ActiveRecord::Relationобъекта.

Вы уверены, что вам нужен LIKEзапрос? глядя на это, я думаю, вы могли бы пойти с простым прямым сравнением. Если мое предположение верно, вы можете перегруппировать последнюю часть вашего кода:

@alarmsF = []
towns_from_events = @header.events.collect(&:town)

@alarmsT.each do |alarmsT|
    @alarmsF << alarmsT if towns_from_events.include?(alarmsT.location)
end
Автор: Zippie Размещён: 16.04.2013 04:47
Вопросы из категории :
32x32