Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在ActiveRecord 3中添加自定义选择_Ruby On Rails_Postgresql_Activerecord_Ruby On Rails 3.2_Postgis - Fatal编程技术网

Ruby on rails 在ActiveRecord 3中添加自定义选择

Ruby on rails 在ActiveRecord 3中添加自定义选择,ruby-on-rails,postgresql,activerecord,ruby-on-rails-3.2,postgis,Ruby On Rails,Postgresql,Activerecord,Ruby On Rails 3.2,Postgis,我试图使用自定义查询的结果(两个地理点之间的距离)作为模型属性。最终目标是能够使用该列筛选和排序行,例如: Model.with_distance(point).order(:distance).first 我最初认为我可以在一个范围内使用select;以下是未经消毒的较短版本: scope :with_distance, ->(point) { select("ST_DISTANCE(models.point_in_model, ST_GeographyFromText('#{poin

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

Model.with_distance(point).order(:distance).first
我最初认为我可以在一个范围内使用
select
;以下是未经消毒的较短版本:

scope :with_distance, ->(point) { select("ST_DISTANCE(models.point_in_model, ST_GeographyFromText('#{point.to_s}')) AS distance") }
但是,该范围仅选择距离列,而不检索模型属性:

> Model.with_distance(point)
[#<Model >, #<Model >,...]
>模型。带距离(点)
[#, #,...]
models.*
添加到
select
调用可以解决问题,代价是强制检索每个查询中的整行并忽略其他
select
调用


我如何才能添加一个SELECT子句,而不是替换所有的SELECT子句?

除了默认的SELECT模型之外。*,ActiveRecord通常会添加SELECT子句,而不是替换它们

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

您可以尝试
select\u star
scope

scope :select_star, -> { select("models.*") }
scope :select_star, -> { select(self.arel_table[Arel.star]) } # Arel version, if feeling adventurous
您可以在需要所有列的位置使用哪些列

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

我对
select
行为也有同样的问题。让我们总结一下这些缺点:

  • 默认情况下,在构造查询时,我们以前从未运行过
    select
    ,使用
    Arel.star
    获取所有列
  • 有时,我们不希望ActiveRecord/ARel添加“*”,例如,我们正在构建一些中间查询或统计查询,而这颗星只会增加数据库的工作量(还可能影响在存在属性等情况下运行的ruby回调)
我认为解决方案之一(在Rails 4.2.4上测试,也可以轻松应用于Rails 3)是向模型或ActiveRecord::Base中添加以下代码:

app/models/item.rb 现在,例如,我们在app/models/item.rb中有以下范围

...
scope :some_business_logic_scope, ->{
    # doing some big query
    joins(...).
    where(...).
    select(...) # some virtual attributes
    # we dont need to run the following line any more
    # select(self.arel_table[Arel.star])
}
...
用法
我从来没用过,但阿雷尔听起来很有趣。然而,这迫使开发人员在大多数查询的末尾添加.select_star,而我希望它的默认值与Rails相同。。。使用默认的“全选”方法对查询进行原型化,然后通过在需要的地方添加select调用进行优化,这会更容易。
...
# include "items".* by default
default_scope ->{select(arel_table[Arel.star])}
# when we dont want to use all columns
scope :no_columns, ->{except(:select)}
...
...
scope :some_business_logic_scope, ->{
    # doing some big query
    joins(...).
    where(...).
    select(...) # some virtual attributes
    # we dont need to run the following line any more
    # select(self.arel_table[Arel.star])
}
...
Item.select(:id) # selects all columns
Item.no_columns.select(:id) # selects only column id
Item.no_columns.some_business_logic_scope # selects only required columns
Item.some_business_logic_scope # selects all attributes including those added by some_business_logic_scope