4

我有 3 张桌子:Objects, Locations, Hotels.

每个对象有几个位置,每个位置有几个酒店(默认在 20 英里半径范围内)。

我的模型(稍微简化一下以专注于主要内容)

对象.rb

attr_accessible :name

has_many :locations
has_many :hotels

位置.rb

attr_accessible :name, :address, :longitude, :latitude

has_many :objects
has_many :hotels

酒店.rb

attr_accessible :name, :address, :longitude, :latitude

has_many :objects
has_many :locations

我想创建一个搜索表单,用户可以在其中输入 Object's namesearch radius

输出应该是所有酒店的列表,这些酒店位于距离每个位置中心的给定半径(小于或等于 20 英里)内,对应于对象。

我想使用Geocoder 的gem 方法near,但我不确定如何构建此类任务的控制器层。

在此处输入图像描述

4

1 回答 1

3

您希望数据库中的空间查询引擎来执行这些查询,例如 MongoDB 或 PostGIS(在 Postgres 中)。我认为您正在寻找的答案会因您使用的答案而异。我将 PostGIS 用于这些东西并且非常喜欢它。

也就是说,Geocoder 可以在没有空间查询引擎的情况下在内部为其提供动力,尽管它的效率不会那么高。如果你变得非常大,它会停止运转。如果您查看来源:https ://github.com/alexreisner/geocoder/blob/master/lib/geocoder/stores/active_record.rb

# skeleton for the controller method
obj = Object.find(name)
locations = obj.locations
near_hotels = locations.map do |loc| 
  locations.hotels.near([loc.latitude, loc.longitude])
end

不确定 near 方法是否正确采用了 radius 参数,但是您可以通过基本上复制它来轻松编写自己的方法:

# on the hotel class
def nearby(lat, lon, radius)
    options = self.send(:near_scope_options, lat, lon, radius, {})
    select(options[:select]).where(options[:conditions]).
      order(options[:order])
}

我强烈建议您查看 PostGIS。

请注意,我的示例方法会产生关系。您可以通过将范围限定为与您的对象匹配的酒店来缩小选择范围。

于 2013-04-12T14:06:13.997 回答