Und*_*ndo 9 activerecord ruby-on-rails rails-activerecord
我有一个方便的范围,includes相关的模型,以加快表格的渲染等:
class Post < ApplicationRecord
...
scope :includes_for_post_row, -> { includes(:reasons).includes(:feedbacks => [:user]) }
Run Code Online (Sandbox Code Playgroud)
它工作正常.但是,现在,我想要select一个额外的属性.如果我已经知道我想要的初始属性,我可以这样做(在控制台中):
2.3.3 :005 > Post.select("`posts`.*, 42 AS column_forty_two").last.column_forty_two
Post Load (1.0ms) SELECT `posts`.*, 42 AS column_forty_two FROM `posts` ORDER BY `posts`.`id` DESC LIMIT 1
=> 42
Run Code Online (Sandbox Code Playgroud)
这假设我知道我想选择posts.*,然后我只是在我的column_forty_two专栏上,这一切都有效.
我想在column_forty_two不影响初始选择的情况下添加到我的结果中.例如,这应该工作:
p = Post.select("`posts`.*, 8 as column_eight").includes_for_post_row_with_forty_two
p.last.column_forty_two # => 42
p.last.column_eight # => 8
p.last.some_activerecord_property # => value
Run Code Online (Sandbox Code Playgroud)
应该这样:
p = Post.all.includes_for_post_row_with_forty_two.last
p.last.column_forty_two # => 42
p.last.some_activerecord_property # => value
Run Code Online (Sandbox Code Playgroud)
如何select在不影响或覆盖默认情况下或我之前选择的现有列的情况下添加其他列?.allselect
mu *_*ort 13
如果你去挖掘ActiveRecord源代码(通常是Rails的必要任务),你会看到发生了什么:
def build_select(arel)
if select_values.any?
arel.project(*arel_columns(select_values.uniq))
else
arel.project(@klass.arel_table[Arel.star])
end
end
Run Code Online (Sandbox Code Playgroud)
select_values是您传递给的所有内容的列表,select默认情况下为空数组:
> Model.where(...).select_values
=> []
> Model.where(...).select('a').select_values
=> ["a"]
> Model.where(...).select('a').select('b').select_values
=> ["a", "b"]
Run Code Online (Sandbox Code Playgroud)
当ActiveRecord最终解决构建SELECT子句时,它要么使用你传递给的select(if分支build_select)或者它使用table_name.*(else分支build_select).
在开始添加更多内容之前,您应该能够使用相同的逻辑build_select来确保select_values具有某些内容,以便通过预先填充默认值来执行if和else分支.您可以将自己的版本修补到模块中:build_selectselect_valuestable_name.*selectActiveRecord::QueryMethods
module ActiveRecord
module QueryMethods
def select_append(*fields)
if(!select_values.any?)
fields.unshift(arel_table[Arel.star])
end
select(*fields)
end
end
end
Run Code Online (Sandbox Code Playgroud)
然后说出类似的话:
> Post.select_append('6 as column_six').to_sql
=> "select `posts`.*, 6 as column_six from ..."
Run Code Online (Sandbox Code Playgroud)
而select单独留下"正常" 行为:
> Post.select('11 as column_eleven').to_sql
=> "select 11 as column_eleven from ..."
Run Code Online (Sandbox Code Playgroud)
你当然不需要修补补丁,但这种事情似乎是合理的.
| 归档时间: |
|
| 查看次数: |
1624 次 |
| 最近记录: |