【问题标题】:Access SQL computed columns through ActiveRecord通过 ActiveRecord 访问 SQL 计算列
【发布时间】:2011-07-19 00:52:50
【问题描述】:

我有一个Person 模型,其中包含一个表示出生数据的属性 (birth_date)。

我还有一个叫做age()的方法,它可以计算出这个人的当前年龄。

我现在需要根据人的年龄运行查询,因此我将age() 的逻辑复制为 MySQL 中的计算列。

我无法确定如何使这个附加列成为模型默认选择语句的一部分。

我希望能够像访问 Person 模型的本机属性一样访问年龄,以对其执行查询并访问我的视图中的值。

这可能吗,还是我找错树了?

我以为我可以通过default_scope 或scope 定义额外的字段,但这些方法似乎只能识别现有字段。我还尝试将default_scope 与attr_assessor 结合使用。

我考虑过但不想这样做的可能解决方法:

  • 创建一个名为age 的实际属性并通过使用回调进行填充。日期总是在变化,所以这显然是可靠的。

  • 将 ActiveRecord 中的逻辑复制为 age(),并在范围内复制为 where 原因。这将达到我的需要,但感觉不是很干燥。

  • 我已经缓存了age() 方法的结果。我最感兴趣的是在 where 子句中使用字段的能力。

一定有办法通过SQL定义动态字段,我默认可以通过模型访问。

任何帮助将不胜感激。

丰富

更新

我尝试使用范围失败的示例:

default_scope :select => "*, 2 as age"

attr_accessor :age

age 是空白的,我认为是因为作用域只处理限制,而不是扩展。

【问题讨论】:

  • 请显示一些代码。您是否为其他属性设置了一些别名,例如 select('expression AS alias') ?
  • @taro,我添加了一个例子。
  • 我认为,attr_accessor 声明是不需要的。
  • 很好,但我不在乎奖品:)
  • @kim3er:您可以在Rails API 中了解命名范围内的 lambda 函数。对于您的问题,它将是:scope :age, lambda {|age| :conditions => ["age(birch_date) > ?", age] }。或者只使用many possibilities 之一来计算此范围内的实际年龄。

标签: mysql ruby-on-rails activerecord calculated-columns


【解决方案1】:

kim3er 您解决问题的方法很简单。请按以下步骤操作:

从您的模型中松开 attr_accessor :age。你根本不需要它。

保留Person 模型的默认范围:default_scope :select => "*, 2 as age"

最后打开控制台试试

p = Person.first
p.age
=> 2

当您使用 as 定义选择时,Rails 会自动为您在实例上添加这些方法!所以你的问题的答案:

一定有办法通过SQL定义动态字段,我默认可以通过模型访问。

是:

导轨

【讨论】:

  • 谢谢格里。 @taro 已经在上面的 cmets 中回答了我的问题,但我感谢您提供的额外上下文,所以我会将问题标记为已回答。
【解决方案2】:

无论如何我都不是专家,但您似乎想要:

class Person < ActiveRecord::Base

scope :exact_age, lambda { |a| where('age = ?', a) }
scope :age_gt, lambda { |a| where('age > ?', a) }

不过话说回来,我刚开始看Arel,看起来很酷

【讨论】:

  • +1 谢谢@Michael K Madison,Arel 看起来很漂亮,我会去看看。
  • 谢谢。再看看Metawhere好像更简单!
猜你喜欢
  • 2013-09-08
  • 1970-01-01
  • 1970-01-01
  • 2013-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多