在 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 对象的创建以仅返回一个数组。
有什么建议么?这可能是一个简单的插件吗?