Получить идентификаторы элементов в именованной области - PullRequest
1 голос
/ 27 марта 2009

В 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, чтобы просто вернуть массив.

Есть предложения? Может ли это быть простой плагин для записи?

Ответы [ 3 ]

2 голосов
/ 27 марта 2009

Вместо того, чтобы создавать дополнительный метод, вы могли бы создать метод на прокси-сервере ассоциации с именем «ids», чтобы вы могли сделать, например, это:

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

И да, для меня это звучит как разумный плагин. Не должно быть слишком сложно писать.

1 голос
/ 17 мая 2014

Поскольку я изначально задавал этот вопрос, Rails добавил оба метода .ids и .pluck в модуль Calculations. Это решило бы мою проблему в то время.

отрыв: https://www.omniref.com/ruby/gems/activerecord/4.1.0/classes/ActiveRecord::Calculations##pluck

идентификаторы: https://www.omniref.com/ruby/gems/activerecord/4.1.0/classes/ActiveRecord::Calculations##ids

0 голосов
/ 29 июня 2011

Просто чтобы взглянуть на это иначе - почему вы беспокоитесь об этом? Сколько памяти вы используете? Похоже, что вы пытаетесь что-то оптимизировать - но если есть только несколько строк (то есть меньше, чем несколько сотен) - я не могу понять, почему вы этим обеспокоены.

У вас есть проблема или вы ее себе представляете?

Не забудьте: http://en.wikipedia.org/wiki/Program_optimization#When_to_optimize

: - D

...