Skip to content

Commit 15be8e8

Browse files
David Padillakarmi
authored andcommitted
[MODEL] Added the :includes option to Adapter::ActiveRecord::Records
This patch adds the `:includes` option to ActiveRecord adapter which can be used to eager load submodels just like you'd do with regular ActiveRecord. This helps to eliminate the N+1 problem when using elasticsearch-model searches. Example: class Article < ActiveRecord::Base belongs_to :author # ... end Article.search(...).records(includes: [:author]) # Would be similar to using: Article.includes(:author).where(...) Closes elastic#472
1 parent a714d59 commit 15be8e8

File tree

4 files changed

+22
-2
lines changed

4 files changed

+22
-2
lines changed

elasticsearch-model/lib/elasticsearch/model/adapters/active_record.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,17 @@ module ActiveRecord
1010
lambda { |klass| !!defined?(::ActiveRecord::Base) && klass.respond_to?(:ancestors) && klass.ancestors.include?(::ActiveRecord::Base) }
1111

1212
module Records
13+
attr_writer :options
14+
15+
def options
16+
@options ||= {}
17+
end
18+
1319
# Returns an `ActiveRecord::Relation` instance
1420
#
1521
def records
1622
sql_records = klass.where(klass.primary_key => ids)
23+
sql_records = sql_records.includes(self.options[:includes]) if self.options[:includes]
1724

1825
# Re-order records based on the order from Elasticsearch hits
1926
# by redefining `to_a`, unless the user has called `order()`

elasticsearch-model/lib/elasticsearch/model/response.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ def results
4444
#
4545
# @return [Records]
4646
#
47-
def records
48-
@records ||= Records.new(klass, self)
47+
def records(options = {})
48+
@records ||= Records.new(klass, self, options)
4949
end
5050

5151
# Returns the "took" time

elasticsearch-model/lib/elasticsearch/model/response/records.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ class Records
1212

1313
delegate :each, :empty?, :size, :slice, :[], :to_a, :to_ary, to: :records
1414

15+
attr_accessor :options
16+
1517
include Base
1618

1719
# @see Base#initialize
@@ -25,6 +27,7 @@ def initialize(klass, response, options={})
2527
metaclass = class << self; self; end
2628
metaclass.__send__ :include, adapter.records_mixin
2729

30+
self.options = options
2831
self
2932
end
3033

elasticsearch-model/test/unit/adapter_active_record_test.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,16 @@ def ids
5151
instance.load
5252
end
5353

54+
should "load the records with its submodels when using :includes" do
55+
klass = mock('class', primary_key: :some_key, where: @records)
56+
@records.expects(:includes).with([:submodel]).at_least_once
57+
58+
instance = DummyClassForActiveRecord.new
59+
instance.expects(:klass).returns(klass).at_least_once
60+
instance.options[:includes] = [:submodel]
61+
instance.records
62+
end
63+
5464
should "reorder the records based on hits order" do
5565
@records.instance_variable_set(:@records, @records)
5666

0 commit comments

Comments
 (0)