通过自定义方法的ActiveRecord作用域



假设我有一个名为Property的类,我正在使用PostGIS适配器来跟踪物理属性(如房子、办公室等)之间的空间关系。我还使用RGeo-gem来跟踪各个属性的位置。

因此,如果我调用:

p = Property.first
p.location # => #<RGeo::Geographic::ProjectedPointImpl:0x3f9303eecc3c "POINT (-111.67226 33.231371)">
p.location.latitude # => 33.231371

我在属性模型中还有一个自定义方法:

class Property < ActiveRecord::Base
...
def lat
self[:location].latitude
end
end
p.lat # => 33.231371

我想创建一个类似于"纬度小于x"或"经度大于x"的范围。

但是,如果我在控制台中键入

irb> Property.where("lat > ?", 30)
# => ActiveRecord::StatementInvalid: PG::Error: ERROR:  column "lat" does not exist

如果我尝试一个看起来像的范围

class Property < ActiveRecord::Base
...
scope :lat_lt, lambda {|val| where(['properties.location.latitude <= ?', val]) }
end

然后我得到

irb> Property.lat_lt "30"
# => Property Load (1.3ms)  SELECT "properties".* FROM "properties" WHERE (properties.location.latitude <= '30')
# => ActiveRecord::StatementInvalid: PG::Error: ERROR:  schema "properties" does not exist

因此,基本上没有"lat"列,尽管我可以在Property实例上调用.lat并获得所需的信息。现在,我只需要能够创建一种通过该返回值确定作用域的方法,即使没有列。

我很想了解更多关于它如何工作的信息;ActiveRecord查询是否在一个不知道模型上定义的方法,即数据库中不存在的方法的级别上运行?

如有任何帮助,我们将不胜感激。

当您使用where方法(或AR查询界面中的任何其他方法)时:http://guides.rubyonrails.org/active_record_querying.html)您正在构建一个sql查询,该查询将在需要时执行。由于您的数据库无法访问您的代码,因此它不知道您定义的方法——它只能访问数据库中存储的内容。

如果您希望基于自定义方法获得结果,您可以1.获取所有属性的列表,然后使用select方法进行筛选(http://www.ruby-doc.org/core-2.1.0/Array.html#method-i-select)-但这可能会带来相当严重的性能和资源问题。2.(推荐)找出如何使用纯sql获得您想要的内容。

如果您能展示位置是如何存储在数据库中的,我会尽力提供进一步的帮助。

相关内容

  • 没有找到相关文章

最新更新