使用地理编码器has_many和belongs_to关联非常奇怪的结果

时间:2015-06-17 15:44:39

标签: ruby-on-rails rails-geocoder

我正在使用Geocoder Gem,它显示有线行为。

我有位置模型

class Location < ActiveRecord::Base
has_many :events
geocoded_by :address
after_validation :geocode
def full_address
    "#{postal_code}, #{city}, #{street}"
  end
end

和事件模型

class Event < ActiveRecord::Base
    belongs_to :location
    accepts_nested_attributes_for :location
end

我想查找当前用户所在位置附近的所有活动。

我尝试按照以下步骤查找附近的位置..

nearby_loc = current_user_location.nearby

它将返回附近的所有地点&#34;当前用户的位置

然后我试了

nearby_loc.events

但它给了我错误

NoMethodError: undefined method `events' for #<ActiveRecord::Relation::ActiveRecord_Relation_Location:0x0000000958c088>

请帮帮我......

4 个答案:

答案 0 :(得分:2)

我更喜欢用我想要的模型开始查询。而不是从集合和#34;中获取&#34;集合,你可以......

加入Location所有活动,以便您可以抓取Event匹配特定条件的所有Location个。大多数情况下,范围只是一系列条件,可以是merge d。

像这样:

Event.joins(:location)                    # Results in `INNER JOIN`
     .merge(current_user_location.nearby) # Adds in the conditions for locations

但事情并非那么简单!

Geocoder做了一个非常复杂的select,并添加了一些有用的字段,如distance,这些字段取决于输入到范围内的点。我们不能失去这些,对吧?该查询将不再有任何意义。

选项是以非常奇怪的方式执行INNER JOIN :指定FROM - 子句以从两个表获取数据(稍后会详细介绍)并在WHERE - 子句中指定连接条件。我们需要一点Arel,所以请提前取出表格:

locations = Location.arel_table
events    = Event   .arel_table # Yeah, call me an indentation maniac

现在这里有一个问题:我们将使用由locations组成的子查询结果,而不是current_user_location.nearby表。怎么样?我们会向from提供一系列我们想要使用的内容:

Event.from([current_user_location.nearby.as('locations'), events])
           # ^ an array, yeah!

我们在这里有:

select events.* from (geocoder subquery) locations, events

现在怎样?连接条件。正如我所说,由于我们正在进行奇怪的加入,我们将在where中指定加入条件。我们必须。

Event.from([current_user_location.nearby.as('locations'), events])
     .where(location_id: locations[:id])

......这应该可以正常工作。完全由数据库完成。

答案 1 :(得分:2)

在这种情况下

nearby_loc = current_user_location.nearby

返回位置列表,而不是单个位置。

要遍历它们并找到每个位置的事件,您可以使用

nearby_events = nearby_loc.map {|loc| loc.events}

但是,就总查询而言,这并不高效。

答案 2 :(得分:1)

events在某个位置定义,并且 nearby将为您提供位置列表,因此您必须遍历列表。

简单地说:

all_related_events  = []
nearby_locations.includes(:events).each do |location|
  all_related_events += location.events
end 

如果您的变量名称更准确地反映了它们包含的内容,也会有所帮助,因此请使用nearby_locations代替nearby_loc

[更新]

为了最大限度地减少查询次数,我添加了.includes(:events),它将在一次查询中获取所有事件。

答案 3 :(得分:1)

  

NoMethodError:未定义的方法`events&#39;对于   ActiveRecord的::关系:: ActiveRecord_Relation_Location

您的nearby_locActiveRecord::Relation,因此nearby_loc.events会导致错误。您应该遍历nearby_loc以使其正常工作。

nearby_loc.each do |n|
n.events
end