elasticsearch-model 7.2.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/README.md +22 -22
  4. data/Rakefile +7 -6
  5. data/elasticsearch-model.gemspec +5 -5
  6. data/examples/activerecord_associations.rb +1 -1
  7. data/examples/activerecord_custom_analyzer.rb +2 -2
  8. data/gemfiles/{6.0.gemfile → 6.1.gemfile} +6 -6
  9. data/gemfiles/{5.0.gemfile → 7.0.gemfile} +8 -7
  10. data/gemfiles/{3.0.gemfile → 7.1.gemfile} +9 -8
  11. data/lib/elasticsearch/model/adapter.rb +0 -2
  12. data/lib/elasticsearch/model/adapters/active_record.rb +0 -4
  13. data/lib/elasticsearch/model/adapters/default.rb +0 -4
  14. data/lib/elasticsearch/model/adapters/mongoid.rb +9 -11
  15. data/lib/elasticsearch/model/adapters/multiple.rb +0 -1
  16. data/lib/elasticsearch/model/importing.rb +1 -12
  17. data/lib/elasticsearch/model/indexing.rb +6 -19
  18. data/lib/elasticsearch/model/multimodel.rb +1 -10
  19. data/lib/elasticsearch/model/naming.rb +7 -58
  20. data/lib/elasticsearch/model/proxy.rb +6 -7
  21. data/lib/elasticsearch/model/response/result.rb +0 -6
  22. data/lib/elasticsearch/model/searching.rb +2 -3
  23. data/lib/elasticsearch/model/version.rb +1 -1
  24. data/lib/elasticsearch/model.rb +6 -3
  25. data/spec/elasticsearch/model/adapter_spec.rb +0 -11
  26. data/spec/elasticsearch/model/adapters/active_record/associations_spec.rb +48 -76
  27. data/spec/elasticsearch/model/adapters/active_record/basic_spec.rb +6 -78
  28. data/spec/elasticsearch/model/adapters/active_record/import_spec.rb +6 -2
  29. data/spec/elasticsearch/model/adapters/active_record/namespaced_model_spec.rb +1 -5
  30. data/spec/elasticsearch/model/adapters/active_record/pagination_spec.rb +0 -8
  31. data/spec/elasticsearch/model/adapters/active_record/parent_child_spec.rb +1 -4
  32. data/spec/elasticsearch/model/adapters/active_record/serialization_spec.rb +9 -11
  33. data/spec/elasticsearch/model/adapters/mongoid_spec.rb +1 -1
  34. data/spec/elasticsearch/model/adapters/multiple_spec.rb +1 -11
  35. data/spec/elasticsearch/model/importing_spec.rb +6 -35
  36. data/spec/elasticsearch/model/indexing_spec.rb +45 -170
  37. data/spec/elasticsearch/model/module_spec.rb +0 -1
  38. data/spec/elasticsearch/model/multimodel_spec.rb +2 -8
  39. data/spec/elasticsearch/model/naming_spec.rb +0 -68
  40. data/spec/elasticsearch/model/proxy_spec.rb +8 -2
  41. data/spec/elasticsearch/model/response/aggregations_spec.rb +4 -4
  42. data/spec/elasticsearch/model/response/base_spec.rb +0 -1
  43. data/spec/elasticsearch/model/response/pagination/kaminari_spec.rb +3 -4
  44. data/spec/elasticsearch/model/response/pagination/will_paginate_spec.rb +0 -1
  45. data/spec/elasticsearch/model/response/records_spec.rb +0 -1
  46. data/spec/elasticsearch/model/response/response_spec.rb +0 -1
  47. data/spec/elasticsearch/model/response/result_spec.rb +0 -17
  48. data/spec/elasticsearch/model/response/results_spec.rb +0 -1
  49. data/spec/elasticsearch/model/searching_search_request_spec.rb +5 -6
  50. data/spec/spec_helper.rb +9 -11
  51. data/spec/support/app/answer.rb +0 -1
  52. data/spec/support/app/article.rb +0 -2
  53. data/spec/support/app/article_no_type.rb +1 -1
  54. data/spec/support/app/namespaced_book.rb +0 -2
  55. data/spec/support/app/parent_and_child_searchable.rb +6 -4
  56. data/spec/support/app/question.rb +0 -1
  57. metadata +15 -16
  58. data/gemfiles/4.0.gemfile +0 -36
@@ -17,15 +17,10 @@
17
17
 
18
18
  module Elasticsearch
19
19
  module Model
20
-
21
- # Provides methods for getting and setting index name and document type for the model
20
+ # Provides methods for getting and setting index and name for the model
22
21
  #
23
22
  module Naming
24
-
25
- DEFAULT_DOC_TYPE = '_doc'.freeze
26
-
27
23
  module ClassMethods
28
-
29
24
  # Get or set the name of the index
30
25
  #
31
26
  # @example Set the index name for the `Article` model
@@ -64,46 +59,18 @@ module Elasticsearch
64
59
  @index_name = name
65
60
  end
66
61
 
67
- # Get or set the document type
68
- #
69
- # @example Set the document type for the `Article` model
70
- #
71
- # class Article
72
- # document_type "my-article"
73
- # end
74
- #
75
- # @example Directly set the document type for the `Article` model
76
- #
77
- # Article.document_type "my-article"
78
- #
79
- def document_type name=nil
80
- @document_type = name || @document_type || implicit(:document_type)
81
- end
82
-
83
-
84
- # Set the document type
85
- #
86
- # @see document_type
87
- #
88
- def document_type=(name)
89
- @document_type = name
90
- end
91
-
92
62
  private
93
63
 
94
- def implicit(prop)
95
- self.send("default_#{prop}")
96
- end
97
-
98
- def default_index_name
99
- self.model_name.collection.gsub(/\//, '-')
100
- end
64
+ def implicit(prop)
65
+ self.send("default_#{prop}")
66
+ end
101
67
 
102
- def default_document_type; end
68
+ def default_index_name
69
+ self.model_name.collection.gsub(/\//, '-')
70
+ end
103
71
  end
104
72
 
105
73
  module InstanceMethods
106
-
107
74
  # Get or set the index name for the model instance
108
75
  #
109
76
  # @example Set the index name for an instance of the `Article` model
@@ -129,25 +96,7 @@ module Elasticsearch
129
96
  def index_name=(name)
130
97
  @index_name = name
131
98
  end
132
-
133
- # @example Set the document type for an instance of the `Article` model
134
- #
135
- # @article.document_type "my-article"
136
- # @article.__elasticsearch__.update_document
137
- #
138
- def document_type name=nil
139
- @document_type = name || @document_type || self.class.document_type
140
- end
141
-
142
- # Set the document type
143
- #
144
- # @see document_type
145
- #
146
- def document_type=(name)
147
- @document_type = name
148
- end
149
99
  end
150
-
151
100
  end
152
101
  end
153
102
  end
@@ -17,7 +17,6 @@
17
17
 
18
18
  module Elasticsearch
19
19
  module Model
20
-
21
20
  # This module provides a proxy interfacing between the including class and
22
21
  # `Elasticsearch::Model`, preventing the pollution of the including class namespace.
23
22
  #
@@ -45,7 +44,6 @@ module Elasticsearch
45
44
  # # => true
46
45
  #
47
46
  module Proxy
48
-
49
47
  # Define the `__elasticsearch__` class and instance methods in the including class
50
48
  # and register a callback for intercepting changes in the model.
51
49
  #
@@ -53,9 +51,7 @@ module Elasticsearch
53
51
  # module and the functionality is accessible via the proxy.
54
52
  #
55
53
  def self.included(base)
56
-
57
54
  base.class_eval do
58
-
59
55
  # `ClassMethodsProxy` instance, accessed as `MyModel.__elasticsearch__`
60
56
  def self.__elasticsearch__ &block
61
57
  @__elasticsearch__ ||= ClassMethodsProxy.new(self)
@@ -115,15 +111,18 @@ module Elasticsearch
115
111
  @target = target
116
112
  end
117
113
 
118
- # Delegate methods to `@target`
114
+ def self.ruby2_keywords(*) # :nodoc:
115
+ end if RUBY_VERSION < "2.7"
116
+
117
+ # Delegate methods to `@target`. As per [the Ruby 3.0 explanation for keyword arguments](https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/), the only way to work on Ruby <2.7, and 2.7, and 3.0+ is to use `ruby2_keywords`.
119
118
  #
120
- def method_missing(method_name, *arguments, &block)
119
+ ruby2_keywords def method_missing(method_name, *arguments, &block)
121
120
  target.respond_to?(method_name) ? target.__send__(method_name, *arguments, &block) : super
122
121
  end
123
122
 
124
123
  # Respond to methods from `@target`
125
124
  #
126
- def respond_to?(method_name, include_private = false)
125
+ def respond_to_missing?(method_name, include_private = false)
127
126
  target.respond_to?(method_name) || super
128
127
  end
129
128
 
@@ -40,12 +40,6 @@ module Elasticsearch
40
40
  @result['_id']
41
41
  end
42
42
 
43
- # Return document `_type` as `_type`
44
- #
45
- def type
46
- @result['_type']
47
- end
48
-
49
43
  # Delegate methods to `@result` or `@result._source`
50
44
  #
51
45
  def method_missing(name, *arguments)
@@ -37,7 +37,6 @@ module Elasticsearch
37
37
  @options = options
38
38
 
39
39
  __index_name = options[:index] || klass.index_name
40
- __document_type = options[:type] || klass.document_type
41
40
 
42
41
  case
43
42
  # search query: ...
@@ -54,9 +53,9 @@ module Elasticsearch
54
53
  end
55
54
 
56
55
  if body
57
- @definition = { index: __index_name, type: __document_type, body: body }.update options
56
+ @definition = { index: __index_name, body: body }.update options
58
57
  else
59
- @definition = { index: __index_name, type: __document_type, q: q }.update options
58
+ @definition = { index: __index_name, q: q }.update options
60
59
  end
61
60
  end
62
61
 
@@ -17,6 +17,6 @@
17
17
 
18
18
  module Elasticsearch
19
19
  module Model
20
- VERSION = "7.2.0"
20
+ VERSION = '8.0.0'.freeze
21
21
  end
22
22
  end
@@ -62,7 +62,6 @@ when defined?(::WillPaginate)
62
62
  end
63
63
 
64
64
  module Elasticsearch
65
-
66
65
  # Elasticsearch integration for Ruby models
67
66
  # =========================================
68
67
  #
@@ -85,7 +84,7 @@ module Elasticsearch
85
84
  # # ...
86
85
  #
87
86
  module Model
88
- METHODS = [:search, :mapping, :mappings, :settings, :index_name, :document_type, :import]
87
+ METHODS = [:search, :mapping, :mappings, :settings, :index_name, :import]
89
88
 
90
89
  # Adds the `Elasticsearch::Model` functionality to the including class.
91
90
  #
@@ -108,12 +107,16 @@ module Elasticsearch
108
107
  def self.included(base)
109
108
  base.class_eval do
110
109
  include Elasticsearch::Model::Proxy
111
-
112
110
  # Delegate common methods to the `__elasticsearch__` ClassMethodsProxy, unless they are defined already
113
111
  class << self
114
112
  METHODS.each do |method|
115
113
  delegate method, to: :__elasticsearch__ unless self.public_instance_methods.include?(method)
116
114
  end
115
+
116
+ def inherited(subclass)
117
+ super
118
+ Registry.add(subclass) if subclass.is_a?(Class)
119
+ end
117
120
  end
118
121
  end
119
122
 
@@ -18,7 +18,6 @@
18
18
  require 'spec_helper'
19
19
 
20
20
  describe Elasticsearch::Model::Adapter do
21
-
22
21
  before(:all) do
23
22
  class ::DummyAdapterClass; end
24
23
  class ::DummyAdapterClassWithAdapter; end
@@ -37,14 +36,12 @@ describe Elasticsearch::Model::Adapter do
37
36
  end
38
37
 
39
38
  describe '#from_class' do
40
-
41
39
  it 'should return an Adapter instance' do
42
40
  expect(Elasticsearch::Model::Adapter.from_class(DummyAdapterClass)).to be_a(Elasticsearch::Model::Adapter::Adapter)
43
41
  end
44
42
  end
45
43
 
46
44
  describe 'register' do
47
-
48
45
  before do
49
46
  expect(Elasticsearch::Model::Adapter::Adapter).to receive(:register).and_call_original
50
47
  Elasticsearch::Model::Adapter.register(:foo, lambda { |c| false })
@@ -55,7 +52,6 @@ describe Elasticsearch::Model::Adapter do
55
52
  end
56
53
 
57
54
  context 'when a specific adapter class is set' do
58
-
59
55
  before do
60
56
  expect(Elasticsearch::Model::Adapter::Adapter).to receive(:register).and_call_original
61
57
  Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter,
@@ -73,7 +69,6 @@ describe Elasticsearch::Model::Adapter do
73
69
  end
74
70
 
75
71
  describe 'default adapter' do
76
-
77
72
  let(:adapter) do
78
73
  Elasticsearch::Model::Adapter::Adapter.new(DummyAdapterClass)
79
74
  end
@@ -84,11 +79,9 @@ describe Elasticsearch::Model::Adapter do
84
79
  end
85
80
 
86
81
  describe '#records_mixin' do
87
-
88
82
  before do
89
83
  Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter,
90
84
  lambda { |c| c == DummyAdapterClassWithAdapter })
91
-
92
85
  end
93
86
 
94
87
  let(:adapter) do
@@ -101,11 +94,9 @@ describe Elasticsearch::Model::Adapter do
101
94
  end
102
95
 
103
96
  describe '#callbacks_mixin' do
104
-
105
97
  before do
106
98
  Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter,
107
99
  lambda { |c| c == DummyAdapterClassWithAdapter })
108
-
109
100
  end
110
101
 
111
102
  let(:adapter) do
@@ -118,11 +109,9 @@ describe Elasticsearch::Model::Adapter do
118
109
  end
119
110
 
120
111
  describe '#importing_mixin' do
121
-
122
112
  before do
123
113
  Elasticsearch::Model::Adapter::Adapter.register(DummyAdapter,
124
114
  lambda { |c| c == DummyAdapterClassWithAdapter })
125
-
126
115
  end
127
116
 
128
117
  let(:adapter) do
@@ -18,7 +18,6 @@
18
18
  require 'spec_helper'
19
19
 
20
20
  describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
21
-
22
21
  before(:all) do
23
22
  ActiveRecord::Schema.define(version: 1) do
24
23
  create_table :categories do |t|
@@ -76,7 +75,6 @@ describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
76
75
  end
77
76
 
78
77
  context 'when a document is created' do
79
-
80
78
  before do
81
79
  Post.create!(title: 'Test')
82
80
  Post.create!(title: 'Testing Coding')
@@ -97,9 +95,7 @@ describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
97
95
  end
98
96
 
99
97
  describe 'has_many_and_belongs_to association' do
100
-
101
- context 'when an association is updated' do
102
-
98
+ context 'when an association is updated' do
103
99
  before do
104
100
  post.categories = [category_a, category_b]
105
101
  Post.__elasticsearch__.refresh_index!
@@ -119,20 +115,20 @@ describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
119
115
 
120
116
  let(:search_result) do
121
117
  Post.search(query: {
122
- bool: {
123
- must: {
124
- multi_match: {
125
- fields: ['title'],
126
- query: 'first'
127
- }
128
- },
129
- filter: {
130
- terms: {
131
- categories: ['One']
132
- }
133
- }
134
- }
135
- } )
118
+ bool: {
119
+ must: {
120
+ multi_match: {
121
+ fields: ['title'],
122
+ query: 'first'
123
+ }
124
+ },
125
+ filter: {
126
+ terms: {
127
+ categories: ['One']
128
+ }
129
+ }
130
+ }
131
+ } )
136
132
  end
137
133
 
138
134
  it 'applies the update with' do
@@ -144,7 +140,6 @@ describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
144
140
  end
145
141
 
146
142
  context 'when an association is deleted' do
147
-
148
143
  before do
149
144
  post.categories = [category_a, category_b]
150
145
  post.categories = [category_b]
@@ -165,20 +160,20 @@ describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
165
160
 
166
161
  let(:search_result) do
167
162
  Post.search(query: {
168
- bool: {
169
- must: {
170
- multi_match: {
171
- fields: ['title'],
172
- query: 'first'
173
- }
174
- },
175
- filter: {
176
- terms: {
177
- categories: ['One']
178
- }
179
- }
180
- }
181
- } )
163
+ bool: {
164
+ must: {
165
+ multi_match: {
166
+ fields: ['title'],
167
+ query: 'first'
168
+ }
169
+ },
170
+ filter: {
171
+ terms: {
172
+ categories: ['One']
173
+ }
174
+ }
175
+ }
176
+ } )
182
177
  end
183
178
 
184
179
  it 'applies the update with a reindex' do
@@ -189,9 +184,7 @@ describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
189
184
  end
190
185
 
191
186
  describe 'has_many through association' do
192
-
193
187
  context 'when the association is updated' do
194
-
195
188
  before do
196
189
  author_a = Author.where(first_name: "John", last_name: "Smith").first_or_create!
197
190
  author_b = Author.where(first_name: "Mary", last_name: "Smith").first_or_create!
@@ -210,33 +203,17 @@ describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
210
203
  Post.__elasticsearch__.refresh_index!
211
204
  end
212
205
 
213
- context 'if active record is at least 4' do
214
-
215
- let(:search_result) do
216
- Post.search('authors.full_name:john')
217
- end
218
-
219
- it 'applies the update', if: active_record_at_least_4? do
220
- expect(search_result.results.size).to eq(2)
221
- expect(search_result.records.size).to eq(2)
222
- end
206
+ let(:search_result) do
207
+ Post.search('authors.full_name:john')
223
208
  end
224
209
 
225
- context 'if active record is less than 4' do
226
-
227
- let(:search_result) do
228
- Post.search('authors.author.full_name:john')
229
- end
230
-
231
- it 'applies the update', if: !active_record_at_least_4? do
232
- expect(search_result.results.size).to eq(2)
233
- expect(search_result.records.size).to eq(2)
234
- end
210
+ it 'applies the update' do
211
+ expect(search_result.results.size).to eq(2)
212
+ expect(search_result.records.size).to eq(2)
235
213
  end
236
214
  end
237
215
 
238
- context 'when an association is added', if: active_record_at_least_4? do
239
-
216
+ context 'when an association is added' do
240
217
  before do
241
218
  author_a = Author.where(first_name: "John", last_name: "Smith").first_or_create!
242
219
  author_b = Author.where(first_name: "Mary", last_name: "Smith").first_or_create!
@@ -262,9 +239,7 @@ describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
262
239
  end
263
240
 
264
241
  describe 'has_many association' do
265
-
266
- context 'when an association is added', if: active_record_at_least_4? do
267
-
242
+ context 'when an association is added' do
268
243
  before do
269
244
  # Create posts
270
245
  post_1 = Post.create!(title: "First Post", text: "This is the first post...")
@@ -282,18 +257,18 @@ describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
282
257
 
283
258
  let(:search_result) do
284
259
  Post.search(query: {
285
- nested: {
286
- path: 'comments',
287
- query: {
288
- bool: {
289
- must: [
290
- { match: { 'comments.author' => 'john' } },
291
- { match: { 'comments.text' => 'good' } }
292
- ]
293
- }
294
- }
295
- }
296
- })
260
+ nested: {
261
+ path: 'comments',
262
+ query: {
263
+ bool: {
264
+ must: [
265
+ { match: { 'comments.author' => 'john' } },
266
+ { match: { 'comments.text' => 'good' } }
267
+ ]
268
+ }
269
+ }
270
+ }
271
+ })
297
272
  end
298
273
 
299
274
  it 'adds the association' do
@@ -303,9 +278,7 @@ describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
303
278
  end
304
279
 
305
280
  describe '#touch' do
306
-
307
281
  context 'when a touch callback is defined on the model' do
308
-
309
282
  before do
310
283
  # Create categories
311
284
  category_a = Category.where(title: "One").first_or_create!
@@ -329,7 +302,6 @@ describe 'Elasticsearch::Model::Adapter::ActiveRecord Associations' do
329
302
  end
330
303
 
331
304
  describe '#includes' do
332
-
333
305
  before do
334
306
  post_1 = Post.create(title: 'One')
335
307
  post_2 = Post.create(title: 'Two')