所以,假设我有一个名为Property的类,我正在使用PostGIS适配器来跟踪物理属性(如房子,办公室等)之间的空间关系。我也在使用RGeo gem来保持跟踪个别物业的位置。
因此,如果我打电话:
p = Property.first
p.location # => #<RGeo::Geographic::ProjectedPointImpl:0x3f9303eecc3c "POINT (-111.67226 33.231371)">
p.location.latitude # => 33.231371
我在Property模型中也有一个自定义方法:
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查询操作的级别是不知道在模型上定义的方法,在数据库中不存在的方法?
非常感谢任何和所有帮助。
答案 0 :(得分:1)
当您使用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获得你想要的东西。
如果您可以显示位置在db中的存储方式,我会尝试进一步提供帮助。