Skip to content

Commit 2a5f57b

Browse files
authored
[MODEL] Ensure that specified ActiveRecord order is not overwritten by Elasticsearch search results order (#835)
* [MODEL] Ensure that specified ActiveRecord order is not overwritten by Elasticsearch query order * [MODEL] Remove interception of #order method, as ordering is handled by checking order_values in #to_a
1 parent 6c00612 commit 2a5f57b

File tree

3 files changed

+16
-29
lines changed

3 files changed

+16
-29
lines changed

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

+5-25
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ def records
3535
else
3636
self.__send__(:exec_queries)
3737
end
38-
@records.sort_by { |record| hits.index { |hit| hit['_id'].to_s == record.id.to_s } }
38+
if !self.order_values.present?
39+
@records.sort_by { |record| hits.index { |hit| hit['_id'].to_s == record.id.to_s } }
40+
else
41+
@records
42+
end
3943
end if self
4044
end
4145

@@ -47,30 +51,6 @@ def records
4751
def load
4852
records.__send__(:load)
4953
end
50-
51-
# Intercept call to the `order` method, so we can ignore the order from Elasticsearch
52-
#
53-
def order(*args)
54-
sql_records = records.__send__ :order, *args
55-
56-
# Redefine the `to_a` method to the original one
57-
#
58-
sql_records.instance_exec do
59-
ar_records_method_name = :to_a
60-
ar_records_method_name = :records if defined?(::ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 5
61-
62-
define_singleton_method(ar_records_method_name) do
63-
if defined?(::ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 4
64-
self.load
65-
else
66-
self.__send__(:exec_queries)
67-
end
68-
@records
69-
end
70-
end
71-
72-
sql_records
73-
end
7454
end
7555

7656
module Callbacks

elasticsearch-model/spec/elasticsearch/model/adapters/active_record_spec.rb

+4-4
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class DummyClassForActiveRecord; end
6666
let(:instance) do
6767
model.tap do |inst|
6868
allow(inst).to receive(:klass).and_return(double('class', primary_key: :some_key, where: records)).at_least(:once)
69+
allow(inst).to receive(:order).and_return(double('class', primary_key: :some_key, where: records)).at_least(:once)
6970
end
7071
end
7172

@@ -95,6 +96,7 @@ class DummyClassForActiveRecord; end
9596

9697
before do
9798
records.instance_variable_set(:@records, records)
99+
allow(records).to receive(:order_values).and_return([])
98100
end
99101

100102
it 'reorders the records based on hits order' do
@@ -109,14 +111,12 @@ class DummyClassForActiveRecord; end
109111
context 'when the records have a different order than the hits' do
110112

111113
before do
112-
records.instance_variable_set(:@records, records)
113-
expect(instance.records).to receive(:order).and_return(records)
114+
records.instance_variable_set(:@records, [record_2, record_1])
115+
allow(records).to receive(:order_values).and_return([double('order_definition')])
114116
end
115117

116118
it 'reorders the records based on hits order' do
117-
expect(records.collect(&:id)).to eq([1, 2])
118119
expect(instance.records.to_a.collect(&:id)).to eq([2, 1])
119-
expect(instance.order(:foo).to_a.collect(&:id)).to eq([1, 2])
120120
end
121121
end
122122
end

elasticsearch-model/test/integration/active_record_basic_test.rb

+7
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,13 @@ def as_indexed_json(options = {})
231231
end
232232
end
233233

234+
should "allow ordering following any method chain in SQL" do
235+
if defined?(::ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 4
236+
response = Article.search query: { match: { title: { query: 'test' } } }
237+
assert_equal 'Testing Coding', response.records.distinct.order(id: :desc).first.title
238+
end
239+
end
240+
234241
should "allow dot access to response" do
235242
response = Article.search query: { match: { title: { query: 'test' } } },
236243
aggregations: {

0 commit comments

Comments
 (0)