elasticsearch-model 5.1.0 → 6.1.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 (125) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/README.md +18 -11
  4. data/Rakefile +27 -36
  5. data/elasticsearch-model.gemspec +5 -5
  6. data/examples/activerecord_custom_analyzer.rb +135 -0
  7. data/examples/activerecord_mapping_completion.rb +3 -18
  8. data/examples/datamapper_article.rb +11 -1
  9. data/gemfiles/3.0.gemfile +6 -1
  10. data/gemfiles/4.0.gemfile +7 -1
  11. data/gemfiles/5.0.gemfile +7 -1
  12. data/lib/elasticsearch/model/adapters/active_record.rb +7 -23
  13. data/lib/elasticsearch/model/adapters/mongoid.rb +10 -3
  14. data/lib/elasticsearch/model/importing.rb +1 -1
  15. data/lib/elasticsearch/model/indexing.rb +6 -4
  16. data/lib/elasticsearch/model/naming.rb +9 -2
  17. data/lib/elasticsearch/model/response/aggregations.rb +1 -1
  18. data/lib/elasticsearch/model/response/base.rb +3 -2
  19. data/lib/elasticsearch/model/response/pagination/kaminari.rb +109 -0
  20. data/lib/elasticsearch/model/response/pagination/will_paginate.rb +95 -0
  21. data/lib/elasticsearch/model/response/pagination.rb +2 -192
  22. data/lib/elasticsearch/model/response/result.rb +1 -1
  23. data/lib/elasticsearch/model/response/suggestions.rb +1 -1
  24. data/lib/elasticsearch/model/response.rb +11 -10
  25. data/lib/elasticsearch/model/version.rb +1 -1
  26. data/lib/elasticsearch/model.rb +15 -8
  27. data/spec/elasticsearch/model/adapter_spec.rb +119 -0
  28. data/spec/elasticsearch/model/adapters/active_record/associations_spec.rb +334 -0
  29. data/spec/elasticsearch/model/adapters/active_record/basic_spec.rb +340 -0
  30. data/spec/elasticsearch/model/adapters/active_record/dynamic_index_name_spec.rb +18 -0
  31. data/spec/elasticsearch/model/adapters/active_record/import_spec.rb +187 -0
  32. data/spec/elasticsearch/model/adapters/active_record/multi_model_spec.rb +110 -0
  33. data/spec/elasticsearch/model/adapters/active_record/namespaced_model_spec.rb +38 -0
  34. data/spec/elasticsearch/model/adapters/active_record/pagination_spec.rb +315 -0
  35. data/spec/elasticsearch/model/adapters/active_record/parent_child_spec.rb +75 -0
  36. data/spec/elasticsearch/model/adapters/active_record/serialization_spec.rb +61 -0
  37. data/spec/elasticsearch/model/adapters/active_record_spec.rb +207 -0
  38. data/spec/elasticsearch/model/adapters/default_spec.rb +41 -0
  39. data/spec/elasticsearch/model/adapters/mongoid/basic_spec.rb +267 -0
  40. data/spec/elasticsearch/model/adapters/mongoid/multi_model_spec.rb +66 -0
  41. data/spec/elasticsearch/model/adapters/mongoid_spec.rb +235 -0
  42. data/spec/elasticsearch/model/adapters/multiple_spec.rb +125 -0
  43. data/spec/elasticsearch/model/callbacks_spec.rb +33 -0
  44. data/spec/elasticsearch/model/client_spec.rb +66 -0
  45. data/spec/elasticsearch/model/hash_wrapper_spec.rb +12 -0
  46. data/spec/elasticsearch/model/importing_spec.rb +214 -0
  47. data/spec/elasticsearch/model/indexing_spec.rb +918 -0
  48. data/spec/elasticsearch/model/module_spec.rb +101 -0
  49. data/spec/elasticsearch/model/multimodel_spec.rb +55 -0
  50. data/spec/elasticsearch/model/naming_inheritance_spec.rb +184 -0
  51. data/spec/elasticsearch/model/naming_spec.rb +186 -0
  52. data/spec/elasticsearch/model/proxy_spec.rb +107 -0
  53. data/spec/elasticsearch/model/response/aggregations_spec.rb +66 -0
  54. data/spec/elasticsearch/model/response/base_spec.rb +90 -0
  55. data/spec/elasticsearch/model/response/pagination/kaminari_spec.rb +410 -0
  56. data/spec/elasticsearch/model/response/pagination/will_paginate_spec.rb +262 -0
  57. data/spec/elasticsearch/model/response/records_spec.rb +118 -0
  58. data/spec/elasticsearch/model/response/response_spec.rb +131 -0
  59. data/spec/elasticsearch/model/response/result_spec.rb +122 -0
  60. data/spec/elasticsearch/model/response/results_spec.rb +56 -0
  61. data/spec/elasticsearch/model/searching_search_request_spec.rb +112 -0
  62. data/spec/elasticsearch/model/searching_spec.rb +49 -0
  63. data/spec/elasticsearch/model/serializing_spec.rb +22 -0
  64. data/spec/spec_helper.rb +161 -0
  65. data/spec/support/app/answer.rb +33 -0
  66. data/spec/support/app/article.rb +22 -0
  67. data/spec/support/app/article_for_pagination.rb +12 -0
  68. data/spec/support/app/article_with_custom_serialization.rb +13 -0
  69. data/spec/support/app/article_with_dynamic_index_name.rb +15 -0
  70. data/spec/support/app/author.rb +9 -0
  71. data/spec/support/app/authorship.rb +4 -0
  72. data/spec/support/app/category.rb +3 -0
  73. data/spec/support/app/comment.rb +3 -0
  74. data/spec/support/app/episode.rb +11 -0
  75. data/spec/support/app/image.rb +19 -0
  76. data/spec/support/app/import_article.rb +12 -0
  77. data/spec/support/app/mongoid_article.rb +21 -0
  78. data/spec/support/app/namespaced_book.rb +10 -0
  79. data/spec/support/app/parent_and_child_searchable.rb +24 -0
  80. data/spec/support/app/post.rb +14 -0
  81. data/spec/support/app/question.rb +27 -0
  82. data/spec/support/app/searchable.rb +48 -0
  83. data/spec/support/app/series.rb +11 -0
  84. data/spec/support/app.rb +21 -0
  85. data/spec/support/model.json +1 -0
  86. metadata +134 -90
  87. data/test/integration/active_record_associations_parent_child_test.rb +0 -147
  88. data/test/integration/active_record_associations_test.rb +0 -339
  89. data/test/integration/active_record_basic_test.rb +0 -251
  90. data/test/integration/active_record_custom_serialization_test.rb +0 -67
  91. data/test/integration/active_record_import_test.rb +0 -115
  92. data/test/integration/active_record_namespaced_model_test.rb +0 -54
  93. data/test/integration/active_record_pagination_test.rb +0 -149
  94. data/test/integration/dynamic_index_name_test.rb +0 -52
  95. data/test/integration/mongoid_basic_test.rb +0 -176
  96. data/test/integration/multiple_models_test.rb +0 -176
  97. data/test/support/model.json +0 -1
  98. data/test/test_helper.rb +0 -92
  99. data/test/unit/adapter_active_record_test.rb +0 -157
  100. data/test/unit/adapter_default_test.rb +0 -41
  101. data/test/unit/adapter_mongoid_test.rb +0 -104
  102. data/test/unit/adapter_multiple_test.rb +0 -106
  103. data/test/unit/adapter_test.rb +0 -69
  104. data/test/unit/callbacks_test.rb +0 -31
  105. data/test/unit/client_test.rb +0 -27
  106. data/test/unit/hash_wrapper_test.rb +0 -13
  107. data/test/unit/importing_test.rb +0 -203
  108. data/test/unit/indexing_test.rb +0 -687
  109. data/test/unit/module_test.rb +0 -68
  110. data/test/unit/multimodel_test.rb +0 -38
  111. data/test/unit/naming_inheritance_test.rb +0 -94
  112. data/test/unit/naming_test.rb +0 -103
  113. data/test/unit/proxy_test.rb +0 -98
  114. data/test/unit/response_aggregations_test.rb +0 -46
  115. data/test/unit/response_base_test.rb +0 -40
  116. data/test/unit/response_pagination_kaminari_test.rb +0 -433
  117. data/test/unit/response_pagination_will_paginate_test.rb +0 -398
  118. data/test/unit/response_records_test.rb +0 -91
  119. data/test/unit/response_result_test.rb +0 -90
  120. data/test/unit/response_results_test.rb +0 -31
  121. data/test/unit/response_test.rb +0 -104
  122. data/test/unit/searching_search_request_test.rb +0 -78
  123. data/test/unit/searching_test.rb +0 -41
  124. data/test/unit/serializing_test.rb +0 -17
  125. /data/{test → spec}/support/model.yml +0 -0
@@ -0,0 +1,101 @@
1
+ require 'spec_helper'
2
+
3
+ describe Elasticsearch::Model do
4
+
5
+ describe '#client' do
6
+
7
+ it 'should have a default' do
8
+ expect(Elasticsearch::Model.client).to be_a(Elasticsearch::Transport::Client)
9
+ end
10
+ end
11
+
12
+ describe '#client=' do
13
+
14
+ before do
15
+ Elasticsearch::Model.client = 'Foobar'
16
+ end
17
+
18
+ it 'should allow the client to be set' do
19
+ expect(Elasticsearch::Model.client).to eq('Foobar')
20
+ end
21
+ end
22
+
23
+ describe 'mixin' do
24
+
25
+ before(:all) do
26
+ class ::DummyIncludingModel; end
27
+ class ::DummyIncludingModelWithSearchMethodDefined
28
+ def self.search(query, options={})
29
+ "SEARCH"
30
+ end
31
+ end
32
+
33
+ DummyIncludingModel.__send__ :include, Elasticsearch::Model
34
+ end
35
+
36
+ after(:all) do
37
+ remove_classes(DummyIncludingModel, DummyIncludingModelWithSearchMethodDefined)
38
+ end
39
+
40
+ it 'should include and set up the proxy' do
41
+ expect(DummyIncludingModel).to respond_to(:__elasticsearch__)
42
+ expect(DummyIncludingModel.new).to respond_to(:__elasticsearch__)
43
+ end
44
+
45
+ it 'should delegate methods to the proxy' do
46
+ expect(DummyIncludingModel).to respond_to(:search)
47
+ expect(DummyIncludingModel).to respond_to(:mapping)
48
+ expect(DummyIncludingModel).to respond_to(:settings)
49
+ expect(DummyIncludingModel).to respond_to(:index_name)
50
+ expect(DummyIncludingModel).to respond_to(:document_type)
51
+ expect(DummyIncludingModel).to respond_to(:import)
52
+ end
53
+
54
+ it 'should not interfere with existing methods' do
55
+ expect(DummyIncludingModelWithSearchMethodDefined.search('foo')).to eq('SEARCH')
56
+ end
57
+ end
58
+
59
+ describe '#settings' do
60
+
61
+ it 'allows access to the settings' do
62
+ expect(Elasticsearch::Model.settings).to eq({})
63
+ end
64
+
65
+ context 'when settings are changed' do
66
+
67
+ before do
68
+ Elasticsearch::Model.settings[:foo] = 'bar'
69
+ end
70
+
71
+ it 'persists the changes' do
72
+ expect(Elasticsearch::Model.settings[:foo]).to eq('bar')
73
+ end
74
+ end
75
+
76
+ context 'when \'inheritance_enabled\' is set' do
77
+
78
+ around do |example|
79
+ original_value = Elasticsearch::Model.settings[:inheritance_enabled]
80
+ example.run
81
+ Elasticsearch::Model.settings[:inheritance_enabled] = original_value
82
+ end
83
+
84
+ context 'when \'inheritance_enabled\' is true' do
85
+
86
+ it 'warns with a deprecation message' do
87
+ expect(Elasticsearch::Model).to receive(:warn)
88
+ Elasticsearch::Model.inheritance_enabled = true
89
+ end
90
+ end
91
+
92
+ context 'when \'inheritance_enabled\' is false' do
93
+
94
+ it 'does not warn' do
95
+ expect(Elasticsearch::Model).not_to receive(:warn)
96
+ Elasticsearch::Model.inheritance_enabled = false
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Elasticsearch::Model::Multimodel do
4
+
5
+ let(:multimodel) do
6
+ Elasticsearch::Model::Multimodel.new(model_1, model_2)
7
+ end
8
+
9
+ let(:model_1) do
10
+ double('Foo', index_name: 'foo_index', document_type: 'foo', to_ary: nil)
11
+ end
12
+
13
+ let(:model_2) do
14
+ double('Bar', index_name: 'bar_index', document_type: 'bar', to_ary: nil)
15
+ end
16
+
17
+ it 'has an index name' do
18
+ expect(multimodel.index_name).to eq(['foo_index', 'bar_index'])
19
+ end
20
+
21
+ it 'has an document type' do
22
+ expect(multimodel.document_type).to eq(['foo', 'bar'])
23
+ end
24
+
25
+ it 'has a client' do
26
+ expect(multimodel.client).to eq(Elasticsearch::Model.client)
27
+ end
28
+
29
+ describe 'the model registry' do
30
+
31
+ before(:all) do
32
+
33
+ class JustAModel
34
+ include Elasticsearch::Model
35
+ end
36
+
37
+ class JustAnotherModel
38
+ include Elasticsearch::Model
39
+ end
40
+ end
41
+
42
+ after(:all) do
43
+ remove_classes(JustAModel, JustAnotherModel)
44
+ end
45
+
46
+ let(:multimodel) do
47
+ Elasticsearch::Model::Multimodel.new
48
+ end
49
+
50
+ it 'includes model in the registry' do
51
+ expect(multimodel.models).to include(JustAModel)
52
+ expect(multimodel.models).to include(JustAnotherModel)
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,184 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'naming inheritance' do
4
+
5
+ context 'without using proxy' do
6
+ before(:all) do
7
+ TestBase = Class.new do
8
+ extend ActiveModel::Naming
9
+
10
+ extend Elasticsearch::Model::Naming::ClassMethods
11
+ include Elasticsearch::Model::Naming::InstanceMethods
12
+ end
13
+
14
+ Animal = Class.new TestBase do
15
+ extend ActiveModel::Naming
16
+
17
+ extend Elasticsearch::Model::Naming::ClassMethods
18
+ include Elasticsearch::Model::Naming::InstanceMethods
19
+
20
+ index_name "mammals"
21
+ document_type "mammal"
22
+ end
23
+
24
+ Dog = Class.new Animal
25
+
26
+ module ::MyNamespace
27
+ Dog = Class.new Animal
28
+ end
29
+
30
+ Cat = Class.new Animal do
31
+ extend ActiveModel::Naming
32
+
33
+ extend Elasticsearch::Model::Naming::ClassMethods
34
+ include Elasticsearch::Model::Naming::InstanceMethods
35
+
36
+ index_name "cats"
37
+ document_type "cat"
38
+ end
39
+
40
+ end
41
+
42
+ after(:all) do
43
+ remove_classes(TestBase, Animal, MyNamespace, Cat)
44
+ end
45
+
46
+ around(:all) do |example|
47
+ original_value = Elasticsearch::Model.inheritance_enabled
48
+ Elasticsearch::Model.inheritance_enabled = true
49
+ example.run
50
+ Elasticsearch::Model.inheritance_enabled = original_value
51
+ end
52
+
53
+ describe '#index_name' do
54
+
55
+ it 'returns the default index name' do
56
+ expect(TestBase.index_name).to eq('test_bases')
57
+ expect(TestBase.new.index_name).to eq('test_bases')
58
+ end
59
+
60
+ it 'returns the explicit index name' do
61
+ expect(Animal.index_name).to eq('mammals')
62
+ expect(Animal.new.index_name).to eq('mammals')
63
+
64
+ expect(Cat.index_name).to eq('cats')
65
+ expect(Cat.new.index_name).to eq('cats')
66
+ end
67
+
68
+ it 'returns the ancestor index name' do
69
+ expect(Dog.index_name).to eq('mammals')
70
+ expect(Dog.new.index_name).to eq('mammals')
71
+ end
72
+
73
+ it 'returns the ancestor index name for namespaced models' do
74
+ expect(::MyNamespace::Dog.index_name).to eq('mammals')
75
+ expect(::MyNamespace::Dog.new.index_name).to eq('mammals')
76
+ end
77
+ end
78
+
79
+ describe '#document_type' do
80
+
81
+ it 'returns nil' do
82
+ expect(TestBase.document_type).to eq('_doc')
83
+ expect(TestBase.new.document_type).to eq('_doc')
84
+ end
85
+
86
+ it 'returns the explicit document type' do
87
+ expect(Animal.document_type).to eq('mammal')
88
+ expect(Animal.new.document_type).to eq('mammal')
89
+
90
+ expect(Cat.document_type).to eq('cat')
91
+ expect(Cat.new.document_type).to eq('cat')
92
+ end
93
+
94
+ it 'returns the ancestor document type' do
95
+ expect(Dog.document_type).to eq('mammal')
96
+ expect(Dog.new.document_type).to eq('mammal')
97
+ end
98
+
99
+ it 'returns the ancestor document type for namespaced models' do
100
+ expect(::MyNamespace::Dog.document_type).to eq('mammal')
101
+ expect(::MyNamespace::Dog.new.document_type).to eq('mammal')
102
+ end
103
+ end
104
+ end
105
+
106
+ context 'when using proxy' do
107
+ before(:all) do
108
+ TestBase = Class.new do
109
+ extend ActiveModel::Naming
110
+
111
+ include Elasticsearch::Model
112
+ end
113
+
114
+ Animal = Class.new TestBase do
115
+ index_name "mammals"
116
+ document_type "mammal"
117
+ end
118
+
119
+ Dog = Class.new Animal
120
+
121
+ module MyNamespace
122
+ Dog = Class.new Animal
123
+ end
124
+
125
+ Cat = Class.new Animal do
126
+ index_name "cats"
127
+ document_type "cat"
128
+ end
129
+ end
130
+
131
+ after(:all) do
132
+ remove_classes(TestBase, Animal, MyNamespace, Cat)
133
+ end
134
+
135
+ around(:all) do |example|
136
+ original_value = Elasticsearch::Model.settings[:inheritance_enabled]
137
+ Elasticsearch::Model.settings[:inheritance_enabled] = true
138
+ example.run
139
+ Elasticsearch::Model.settings[:inheritance_enabled] = original_value
140
+ end
141
+
142
+ describe '#index_name' do
143
+
144
+ it 'returns the default index name' do
145
+ expect(TestBase.index_name).to eq('test_bases')
146
+ end
147
+
148
+ it 'returns the explicit index name' do
149
+ expect(Animal.index_name).to eq('mammals')
150
+
151
+ expect(Cat.index_name).to eq('cats')
152
+ end
153
+
154
+ it 'returns the ancestor index name' do
155
+ expect(Dog.index_name).to eq('mammals')
156
+ end
157
+
158
+ it 'returns the ancestor index name for namespaced models' do
159
+ expect(::MyNamespace::Dog.index_name).to eq('mammals')
160
+ end
161
+ end
162
+
163
+ describe '#document_type' do
164
+
165
+ it 'returns nil' do
166
+ expect(TestBase.document_type).to eq('_doc')
167
+ end
168
+
169
+ it 'returns the explicit document type' do
170
+ expect(Animal.document_type).to eq('mammal')
171
+
172
+ expect(Cat.document_type).to eq('cat')
173
+ end
174
+
175
+ it 'returns the ancestor document type' do
176
+ expect(Dog.document_type).to eq('mammal')
177
+ end
178
+
179
+ it 'returns the ancestor document type for namespaced models' do
180
+ expect(::MyNamespace::Dog.document_type).to eq('mammal')
181
+ end
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,186 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'naming' do
4
+
5
+ before(:all) do
6
+ class ::DummyNamingModel
7
+ extend ActiveModel::Naming
8
+
9
+ extend Elasticsearch::Model::Naming::ClassMethods
10
+ include Elasticsearch::Model::Naming::InstanceMethods
11
+ end
12
+
13
+ module ::MyNamespace
14
+ class DummyNamingModelInNamespace
15
+ extend ActiveModel::Naming
16
+
17
+ extend Elasticsearch::Model::Naming::ClassMethods
18
+ include Elasticsearch::Model::Naming::InstanceMethods
19
+ end
20
+ end
21
+ end
22
+
23
+ after(:all) do
24
+ remove_classes(DummyNamingModel, MyNamespace)
25
+ end
26
+
27
+ it 'returns the default index name' do
28
+ expect(DummyNamingModel.index_name).to eq('dummy_naming_models')
29
+ expect(DummyNamingModel.new.index_name).to eq('dummy_naming_models')
30
+ end
31
+
32
+ it 'returns the sanitized defualt index name for namespaced models' do
33
+ expect(::MyNamespace::DummyNamingModelInNamespace.index_name).to eq('my_namespace-dummy_naming_model_in_namespaces')
34
+ expect(::MyNamespace::DummyNamingModelInNamespace.new.index_name).to eq('my_namespace-dummy_naming_model_in_namespaces')
35
+ end
36
+
37
+ it 'returns the document type' do
38
+ expect(DummyNamingModel.document_type).to eq('_doc')
39
+ expect(DummyNamingModel.new.document_type).to eq('_doc')
40
+ end
41
+
42
+ describe '#index_name' do
43
+
44
+ context 'when the index name is set on the class' do
45
+
46
+ before do
47
+ DummyNamingModel.index_name 'foobar'
48
+ end
49
+
50
+ it 'sets the index_name' do
51
+ expect(DummyNamingModel.index_name).to eq('foobar')
52
+ end
53
+ end
54
+
55
+ context 'when the index name is set on an instance' do
56
+
57
+ before do
58
+ instance.index_name 'foobar_d'
59
+ end
60
+
61
+ let(:instance) do
62
+ DummyNamingModel.new
63
+ end
64
+
65
+ it 'sets the index name on the instance' do
66
+ expect(instance.index_name).to eq('foobar_d')
67
+ end
68
+
69
+ context 'when the index name is set with a proc' do
70
+
71
+ before do
72
+ modifier = 'r'
73
+ instance.index_name Proc.new{ "foobar_#{modifier}" }
74
+ end
75
+
76
+ it 'sets the index name on the instance' do
77
+ expect(instance.index_name).to eq('foobar_r')
78
+ end
79
+ end
80
+ end
81
+ end
82
+
83
+ describe '#index_name=' do
84
+
85
+ before do
86
+ DummyNamingModel.index_name = 'foobar_index_S'
87
+ end
88
+
89
+ it 'changes the index name' do
90
+ expect(DummyNamingModel.index_name).to eq('foobar_index_S')
91
+ end
92
+
93
+ context 'when the method is called on an instance' do
94
+
95
+ let(:instance) do
96
+ DummyNamingModel.new
97
+ end
98
+
99
+ before do
100
+ instance.index_name = 'foobar_index_s'
101
+ end
102
+
103
+ it 'changes the index name' do
104
+ expect(instance.index_name).to eq('foobar_index_s')
105
+ end
106
+
107
+ it 'does not change the index name on the class' do
108
+ expect(DummyNamingModel.index_name).to eq('foobar_index_S')
109
+ end
110
+ end
111
+
112
+ context 'when the index name is changed with a proc' do
113
+
114
+ before do
115
+ modifier2 = 'y'
116
+ DummyNamingModel.index_name = Proc.new{ "foobar_index_#{modifier2}" }
117
+ end
118
+
119
+ it 'changes the index name' do
120
+ expect(DummyNamingModel.index_name).to eq('foobar_index_y')
121
+ end
122
+ end
123
+ end
124
+
125
+ describe '#document_type' do
126
+
127
+ it 'returns the document type' do
128
+ expect(DummyNamingModel.document_type).to eq('_doc')
129
+ end
130
+
131
+ context 'when the method is called with an argument' do
132
+
133
+ before do
134
+ DummyNamingModel.document_type 'foo'
135
+ end
136
+
137
+ it 'changes the document type' do
138
+ expect(DummyNamingModel.document_type).to eq('foo')
139
+ end
140
+ end
141
+
142
+ context 'when the method is called on an instance' do
143
+
144
+ let(:instance) do
145
+ DummyNamingModel.new
146
+ end
147
+
148
+ before do
149
+ instance.document_type 'foobar_d'
150
+ end
151
+
152
+ it 'changes the document type' do
153
+ expect(instance.document_type).to eq('foobar_d')
154
+ end
155
+ end
156
+ end
157
+
158
+ describe '#document_type=' do
159
+
160
+ context 'when the method is called on the class' do
161
+
162
+ before do
163
+ DummyNamingModel.document_type = 'foo_z'
164
+ end
165
+
166
+ it 'changes the document type' do
167
+ expect(DummyNamingModel.document_type).to eq('foo_z')
168
+ end
169
+ end
170
+
171
+ context 'when the method is called on an instance' do
172
+
173
+ let(:instance) do
174
+ DummyNamingModel.new
175
+ end
176
+
177
+ before do
178
+ instance.document_type = 'foobar_b'
179
+ end
180
+
181
+ it 'changes the document type' do
182
+ expect(instance.document_type).to eq('foobar_b')
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,107 @@
1
+ require 'spec_helper'
2
+
3
+ describe Elasticsearch::Model::Proxy do
4
+
5
+ before(:all) do
6
+ class ::DummyProxyModel
7
+ include Elasticsearch::Model::Proxy
8
+
9
+ def self.foo
10
+ 'classy foo'
11
+ end
12
+
13
+ def bar
14
+ 'insta barr'
15
+ end
16
+
17
+ def as_json(options)
18
+ {foo: 'bar'}
19
+ end
20
+ end
21
+
22
+ class ::DummyProxyModelWithCallbacks
23
+ def self.before_save(&block)
24
+ (@callbacks ||= {})[block.hash] = block
25
+ end
26
+
27
+ def changes_to_save
28
+ {:foo => ['One', 'Two']}
29
+ end
30
+ end
31
+
32
+ DummyProxyModelWithCallbacks.__send__ :include, Elasticsearch::Model::Proxy
33
+ end
34
+
35
+ after(:all) do
36
+ remove_classes(DummyProxyModel, DummyProxyModelWithCallbacks)
37
+ end
38
+
39
+ it 'sets up a proxy method on the class' do
40
+ expect(DummyProxyModel).to respond_to(:__elasticsearch__)
41
+ end
42
+
43
+ it 'sets up a proxy method on instances' do
44
+ expect(DummyProxyModel.new).to respond_to(:__elasticsearch__)
45
+ end
46
+
47
+ it 'sets up hooks for before_save callbacks' do
48
+ expect(DummyProxyModelWithCallbacks).to respond_to(:before_save)
49
+ end
50
+
51
+ it 'delegates methods to the target' do
52
+ expect(DummyProxyModel.__elasticsearch__).to respond_to(:foo)
53
+ expect(DummyProxyModel.__elasticsearch__.foo).to eq('classy foo')
54
+ expect(DummyProxyModel.new.__elasticsearch__).to respond_to(:bar)
55
+ expect(DummyProxyModel.new.__elasticsearch__.bar).to eq('insta barr')
56
+
57
+ expect {
58
+ DummyProxyModel.__elasticsearch__.xoxo
59
+ }.to raise_exception(NoMethodError)
60
+
61
+ expect {
62
+ DummyProxyModel.new.__elasticsearch__.xoxo
63
+ }.to raise_exception(NoMethodError)
64
+ end
65
+
66
+ it 'returns the proxy class from an instance proxy' do
67
+ expect(DummyProxyModel.new.__elasticsearch__.class.class).to eq(Elasticsearch::Model::Proxy::ClassMethodsProxy)
68
+ end
69
+
70
+ it 'returns the origin class from an instance proxy' do
71
+ expect(DummyProxyModel.new.__elasticsearch__.klass).to eq(DummyProxyModel)
72
+ end
73
+
74
+ it 'delegates #as_json from the proxy to the target' do
75
+ expect(DummyProxyModel.new.__elasticsearch__.as_json).to eq(foo: 'bar')
76
+ end
77
+
78
+ it 'includes the proxy in the inspect string' do
79
+ expect(DummyProxyModel.__elasticsearch__.inspect).to match(/PROXY/)
80
+ expect(DummyProxyModel.new.__elasticsearch__.inspect).to match(/PROXY/)
81
+ end
82
+
83
+ context 'when instances are cloned' do
84
+
85
+ let!(:model) do
86
+ DummyProxyModel.new
87
+ end
88
+
89
+ let!(:model_target) do
90
+ model.__elasticsearch__.target
91
+ end
92
+
93
+ let!(:duplicate) do
94
+ model.dup
95
+ end
96
+
97
+ let!(:duplicate_target) do
98
+ duplicate.__elasticsearch__.target
99
+ end
100
+
101
+ it 'resets the proxy target' do
102
+ expect(model).not_to eq(duplicate)
103
+ expect(model).to eq(model_target)
104
+ expect(duplicate).to eq(duplicate_target)
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ describe Elasticsearch::Model::Response::Aggregations do
4
+
5
+ before(:all) do
6
+ class OriginClass
7
+ def self.index_name; 'foo'; end
8
+ def self.document_type; 'bar'; end
9
+ end
10
+ end
11
+
12
+ after(:all) do
13
+ remove_classes(OriginClass)
14
+ end
15
+
16
+ let(:response_document) do
17
+ {
18
+ 'aggregations' => {
19
+ 'foo' => {'bar' => 10 },
20
+ 'price' => { 'doc_count' => 123,
21
+ 'min' => { 'value' => 1.0},
22
+ 'max' => { 'value' => 99 }
23
+ }
24
+ }
25
+ }
26
+ end
27
+
28
+ let(:search) do
29
+ Elasticsearch::Model::Searching::SearchRequest.new(OriginClass, '*').tap do |request|
30
+ allow(request).to receive(:execute!).and_return(response_document)
31
+ end
32
+ end
33
+
34
+ let(:aggregations) do
35
+ Elasticsearch::Model::Response::Response.new(OriginClass, search).aggregations
36
+ end
37
+
38
+ describe 'method delegation' do
39
+
40
+ it 'delegates methods to the response document' do
41
+ expect(aggregations.foo).to be_a(Hashie::Mash)
42
+ expect(aggregations.foo.bar).to be(10)
43
+ end
44
+ end
45
+
46
+ describe '#doc_count' do
47
+
48
+ it 'returns the doc count value from the response document' do
49
+ expect(aggregations.price.doc_count).to eq(123)
50
+ end
51
+ end
52
+
53
+ describe '#min' do
54
+
55
+ it 'returns the min value from the response document' do
56
+ expect(aggregations.price.min.value).to eq(1)
57
+ end
58
+ end
59
+
60
+ describe '#max' do
61
+
62
+ it 'returns the max value from the response document' do
63
+ expect(aggregations.price.max.value).to eq(99)
64
+ end
65
+ end
66
+ end