简体   繁体   中英

Rails 3.2 - undefined method `where' for #<Array:… - Query of Model.where()

I am trying to compare fields from a given Header to other fields in the Alarm model. As you can see in the code I filter the alarms in 3 different steps. The first 2 work perfectly. However, the last one does not work. It said:

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

As far as I understand .where is a class method that works with array. Why does not work here? I also tried with .find_all_by and different things... but to not avail.

@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

Any help spotting what I am missing much appreciated. Thanks

In your first line, you're successfully returning an ActiveRecordRelation object in @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])

At this point you could apply additional .where(...) methods, conditions or scopes on @alarmsT to further build up the ARel expression and the results returned.

However, you then run a filter over this relation, converting @alarmsT to an instance of 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

You can no longer build up the ARel expression, since Array doesn't know about your ARel's .where(...) method, or any of your Alarm model's scopes or attributes. This is why in the code below you're getting the undefined method 'where' for #<Array:... error -- you're calling .where() on an instance of Array ; a method that does not exist.

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

You can fix this by not doing the select to filter by category ids and instead using a join. Building such a join (to verify existence of at least a subset of values in a related table/column) is documented quite a bit on places easily found through google and here on StackOverflow.

Like @Deefour said, with select you are collecting data in a Array instead of a ActiveRecord::Relation object.

Are you sure you need the LIKE query? by looking at it i guess you could go with a simple straight-forward comparison. If my assumption is true, you could rearange the last part of your code:

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

@alarmsT.each do |alarmsT|
    @alarmsF << alarmsT if towns_from_events.include?(alarmsT.location)
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM