В 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)
В настоящее время я получаю идентификаторы объектов в именованном наборе результатов:
HistoricalSession.recent.map (&: идентификатор). Это по сути похоже на то, что делается в последнем примере выше, и, очевидно, неэффективно. Я не хочу создавать целые объекты HistoricalSession, когда в конце концов мне нужен только массив идентификаторов.
Альтернативной реализацией может быть новый метод .find. Например, HistoricalSession.recent.find_attributes (: id). Этот метод заменит оператор select, чтобы выбрать только указанные значения, и приведет к короткому замыканию создания объекта ActiveRecord, чтобы просто вернуть массив.
Есть предложения? Может ли это быть простой плагин для записи?