我有3个表:Objects
,Locations
,Hotels
。
每个对象都有多个位置,每个位置都有几个酒店(默认半径为20英里)。
我的模型(稍微简化一下,专注于主要事物)
object.rb
attr_accessible :name
has_many :locations
has_many :hotels
location.rb
attr_accessible :name, :address, :longitude, :latitude
has_many :objects
has_many :hotels
hotels.rb
attr_accessible :name, :address, :longitude, :latitude
has_many :objects
has_many :locations
我想创建一个搜索表单,用户可以在其中输入对象的名称和搜索半径。
输出应该是所有酒店的列表,这些酒店位于距离每个位置中心的给定半径(小于或等于20英里)内,对应于对象。
我想使用Geocoder's gem方法near
,但我不确定如何构建此类任务的控制器层。
答案 0 :(得分: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方法是否正确地采用了半径参数,但你可以通过基本上复制它来轻松编写自己的方法:
# 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。
注意,我的示例方法产生了一种关系。您可以通过确定与您的对象匹配的酒店来缩小您的选择范围。