获取命名范围中的元素ID

时间:2009-03-27 06:16:46

标签: ruby-on-rails ruby activerecord named-scope

在ruby on rails上,所有has_many :widgets方法都会生成object.widgets方法和object.widget_ids方法。

后一种方法非常有用,因为它绕过了ActiveRecord对象的创建并运行了更快的查询。使用:select选项可以提高查询速度,但是在生成对象而不是整数时,ruby仍会分配更多的内存。

例如

User has_many :historical_sessions:

>> Benchmark.measure { User.find(4).historical_sessions.map(&:id) }
HistoricalSession Load (131.0ms)   SELECT * FROM `historical_sessions` WHERE (`historical_sessions`.user_id = 4)
=> #<Benchmark::Tms:0xbe805c0 @cutime=0.0, @label="", @total=1.996, @stime=0.0150000000000006, @real=2.09599995613098, @utime=1.981, @cstime=0.0>
(2.1 seconds)

>> Benchmark.measure { User.find(4).historical_session_ids }
HistoricalSession Load (34.0ms)   SELECT `historical_sessions`.id FROM `historical_sessions` WHERE (`historical_sessions`.user_id = 4)
=> #<Benchmark::Tms:0x11e6cd94 @cutime=0.0, @label="", @total=1.529, @stime=0.032, @real=1.55099987983704, @utime=1.497, @cstime=0.0>
(1.6 seconds)

(结果集是67353个对象)

使用named_scopes时是否有办法发生相同的行为?

例如,

User named_scope :recent
User.recent (Exists)
User.recent_ids (Does not exist)

我目前在命名范围结果集中获取对象ID的方式是: HistoricalSession.recent.map(安培;:ID)。这基本上类似于上面后一个例子中所做的,显然效率不高。我不想构建完整的HistoricalSession对象,最后我只需要一个id数组。

备用实现可以是新的.find方法。例如,HistoricalSession.recent.find_attributes(:id)。此方法将替换select语句以仅选择指定的值,并将ActiveRecord对象创建短路以返回数组。

有什么建议吗?这可能是一个简单的插件吗?

3 个答案:

答案 0 :(得分:2)

您可以在关联代理上创建一个名为“ids”的方法,而不是创建其他方法,以便您可以执行以下操作:这样:

User.named_scope :recent, ...
User.named_scope :admin, ...
User.recent.admin.ids

是的,这对我来说听起来像是一个明智的插件。不应该写得太难。

答案 1 :(得分:1)

由于我最初提出这个问题,Rails在Calculations模块中添加了.ids和.pluck方法。这些可以解决我当时的问题。

采摘:https://www.omniref.com/ruby/gems/activerecord/4.1.0/classes/ActiveRecord::Calculations##pluck

ids:https://www.omniref.com/ruby/gems/activerecord/4.1.0/classes/ActiveRecord::Calculations##ids

答案 2 :(得分:0)

在这里采取不同的看法 - 为什么你为此烦恼?你用了多少内存?看起来你正在尝试优化某些东西 - 但是如果只有几行(即少于几百行) - 我不明白为什么你会对此有所了解。

你有问题,还是想象一个?

不要忘记:http://en.wikipedia.org/wiki/Program_optimization#When_to_optimize

: - d