在ActiveRecord 3中添加自定义SELECT

F.X*_*.X. 5 postgresql activerecord postgis ruby-on-rails ruby-on-rails-3.2

我试图使用自定义查询的结果(两个地理点之间的距离)作为模型属性.最终目标是能够使用该列过滤和排序行,例如:

Model.with_distance(point).order(:distance).first
Run Code Online (Sandbox Code Playgroud)

我最初以为我可以select在范围内使用; 这是一个没有消毒的较短版本:

scope :with_distance, ->(point) { select("ST_DISTANCE(models.point_in_model, ST_GeographyFromText('#{point.to_s}')) AS distance") }
Run Code Online (Sandbox Code Playgroud)

但是,该范围仅选择distance列,而不检索模型属性:

> Model.with_distance(point)
[#<Model >, #<Model >,...]
Run Code Online (Sandbox Code Playgroud)

添加models.*select调用可以解决问题,代价是强制检索每个查询中的整行并忽略其他select调用.

如何添加SELECT子句而不是替换所有子句

mes*_*jah 3

除了 default 之外SELECT models.*,ActiveRecord 通常会添加SELECT 子句,而不是替换它们。

> Project.select(:id).select(:name)
=> Project Load (0.5ms)  SELECT id, name FROM "projects"
Run Code Online (Sandbox Code Playgroud)

显然,当您想要“默认 SELECT 以及我要求的任何其他选择”时,这没有帮助。

你可以尝试一下select_star范围

scope :select_star, -> { select("models.*") }
scope :select_star, -> { select(self.arel_table[Arel.star]) } # Arel version, if feeling adventurous
Run Code Online (Sandbox Code Playgroud)

您可以在需要所有列的地方使用它吗?

> Model.with_distance(point).select_star
=> SELECT ST_DISTANCE(models.point_in_model, ST_GeographyFromText('0,0')) AS distance, models.* FROM ...
Run Code Online (Sandbox Code Playgroud)