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)です。これは、上記の後者の例で行われていることと本質的に類似しており、明らかに効率的ではありません。最終的に必要なのはIDの配列だけであるのに、HistoricalSessionオブジェクト全体を構築したくありません。
別の実装は、新しい.findメソッドである可能性があります。たとえば、HistoricalSession.recent.find_attributes(:id)です。このメソッドは、selectステートメントを置き換えて、指定された値のみを選択し、ActiveRecordオブジェクトの作成を短絡して配列を返すだけです。
助言がありますか?これは簡単なプラグインでしょうか?