【问题标题】:Create ActiveRecord attributes without overriding select创建 ActiveRecord 属性而不覆盖选择
【发布时间】:2015-05-03 10:57:54
【问题描述】:

使用 SQL 的 AS 运算符,我们可能会创建与数据库中的真实列不对应的 ActiveRecord 属性:

user = User.select(<<-SQL).first
  *, CONTACT(first_name, ' ', last_name) AS full_name
SQL

user.full_name => "Bob Nastanovich"

我的问题是* 是必要的。我正在编写一个 AR 扩展,它将为 SQL 计算的结果添加虚拟属性,但包括 * 意味着用户将永远无法使用 @ 缩小返回的属性987654325@方法。

除了select 之外,还有什么方法可以通过其他方法添加“计算”属性,同时确保所有工作都由数据库完成?我不希望遍历查询后的结果。我的示例故意非常简单,实际实现涉及对JOIN 的计算。

我无法找到任何关于此的信息,所以我很怀疑,但我想我会问!

【问题讨论】:

  • 您可能会覆盖ActiveRecord::Relation#exec_queries,然后检查arel.projections 是否包含除您的库值之外的任何内容,如果没有,则将* 添加到投影中。
  • 不过,这可能非常依赖于 Rails 版本。
  • 哇,这真的很有趣。绝对不是一个干净或理想的解决方案——特别是因为计算的属性有变量名(嗯,半变量)——但我会玩这个,让你知道它是怎么回事。我已经开始深入研究 AR 源代码,这让我快速跟踪了很多。谢谢!

标签: ruby-on-rails activerecord


【解决方案1】:

您可以通过只选择一个字段来做同样的事情(任何字段都可以):

> user = User.select(<<-SQL).first
>   id, CONTACT(first_name, ' ', last_name) AS full_name
> SQL

> user.full_name
 => "Bob Nastanovich"

> user
  => #<User id: 176488>

> user.attributes
 => {"id"=>176488, "full_name"=>"Bob Nastanovich"}

编辑

没有* 的查询也适用于我:

> user = User.select(<<-SQL).first
>   CONTACT(first_name, ' ', last_name) AS full_name
> SQL

> user.full_name
 => "Bob Nastanovich"

> user
  => #<User id: nil>

> user.attributes
 => {"full_name"=>"Bob Nastanovich", "id"=>nil}

【讨论】:

  • 正如我所提到的,这将在 AR 扩展中,即,它将在库代码中。我想添加 SQL 计算属性,但也允许用户使用select。如果库代码中有select("*"),那么select方法对用户来说基本上是无用的(除了添加其他计算字段)。
  • 没有*,对象将包含计算属性。
猜你喜欢
  • 1970-01-01
  • 2010-09-27
  • 1970-01-01
  • 2019-07-30
  • 1970-01-01
  • 1970-01-01
  • 2017-11-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多