chewy 6.0.0 → 7.6.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 (188) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. data/.github/PULL_REQUEST_TEMPLATE.md +16 -0
  6. data/.github/dependabot.yml +42 -0
  7. data/.github/workflows/ruby.yml +60 -0
  8. data/.rubocop.yml +16 -8
  9. data/.rubocop_todo.yml +110 -22
  10. data/CHANGELOG.md +396 -105
  11. data/CODE_OF_CONDUCT.md +14 -0
  12. data/CONTRIBUTING.md +63 -0
  13. data/Gemfile +4 -10
  14. data/Guardfile +3 -1
  15. data/README.md +497 -275
  16. data/chewy.gemspec +5 -20
  17. data/gemfiles/base.gemfile +12 -0
  18. data/gemfiles/rails.6.1.activerecord.gemfile +10 -15
  19. data/gemfiles/rails.7.0.activerecord.gemfile +14 -0
  20. data/gemfiles/rails.7.1.activerecord.gemfile +14 -0
  21. data/lib/chewy/config.rb +60 -52
  22. data/lib/chewy/elastic_client.rb +31 -0
  23. data/lib/chewy/errors.rb +7 -10
  24. data/lib/chewy/fields/base.rb +79 -13
  25. data/lib/chewy/fields/root.rb +4 -14
  26. data/lib/chewy/index/actions.rb +54 -37
  27. data/lib/chewy/{type → index}/adapter/active_record.rb +30 -6
  28. data/lib/chewy/{type → index}/adapter/base.rb +2 -3
  29. data/lib/chewy/{type → index}/adapter/object.rb +27 -31
  30. data/lib/chewy/{type → index}/adapter/orm.rb +17 -18
  31. data/lib/chewy/index/aliases.rb +14 -5
  32. data/lib/chewy/index/crutch.rb +40 -0
  33. data/lib/chewy/index/import/bulk_builder.rb +311 -0
  34. data/lib/chewy/{type → index}/import/bulk_request.rb +6 -7
  35. data/lib/chewy/{type → index}/import/journal_builder.rb +11 -12
  36. data/lib/chewy/{type → index}/import/routine.rb +18 -17
  37. data/lib/chewy/{type → index}/import.rb +76 -32
  38. data/lib/chewy/{type → index}/mapping.rb +29 -34
  39. data/lib/chewy/index/observe/active_record_methods.rb +87 -0
  40. data/lib/chewy/index/observe/callback.rb +34 -0
  41. data/lib/chewy/index/observe.rb +17 -0
  42. data/lib/chewy/index/specification.rb +1 -0
  43. data/lib/chewy/{type → index}/syncer.rb +59 -59
  44. data/lib/chewy/{type → index}/witchcraft.rb +11 -7
  45. data/lib/chewy/{type → index}/wrapper.rb +2 -2
  46. data/lib/chewy/index.rb +67 -94
  47. data/lib/chewy/journal.rb +25 -14
  48. data/lib/chewy/log_subscriber.rb +5 -1
  49. data/lib/chewy/minitest/helpers.rb +86 -13
  50. data/lib/chewy/minitest/search_index_receiver.rb +24 -26
  51. data/lib/chewy/railtie.rb +6 -20
  52. data/lib/chewy/rake_helper.rb +169 -113
  53. data/lib/chewy/rspec/build_query.rb +12 -0
  54. data/lib/chewy/rspec/helpers.rb +55 -0
  55. data/lib/chewy/rspec/update_index.rb +55 -44
  56. data/lib/chewy/rspec.rb +2 -0
  57. data/lib/chewy/runtime/version.rb +1 -1
  58. data/lib/chewy/runtime.rb +1 -1
  59. data/lib/chewy/search/loader.rb +19 -41
  60. data/lib/chewy/search/parameters/collapse.rb +16 -0
  61. data/lib/chewy/search/parameters/concerns/query_storage.rb +2 -2
  62. data/lib/chewy/search/parameters/ignore_unavailable.rb +27 -0
  63. data/lib/chewy/search/parameters/indices.rb +13 -58
  64. data/lib/chewy/search/parameters/knn.rb +16 -0
  65. data/lib/chewy/search/parameters/order.rb +6 -19
  66. data/lib/chewy/search/parameters/source.rb +5 -1
  67. data/lib/chewy/search/parameters/storage.rb +1 -1
  68. data/lib/chewy/search/parameters/track_total_hits.rb +16 -0
  69. data/lib/chewy/search/parameters.rb +6 -4
  70. data/lib/chewy/search/query_proxy.rb +9 -2
  71. data/lib/chewy/search/request.rb +169 -134
  72. data/lib/chewy/search/response.rb +5 -5
  73. data/lib/chewy/search/scoping.rb +7 -8
  74. data/lib/chewy/search/scrolling.rb +13 -13
  75. data/lib/chewy/search.rb +9 -19
  76. data/lib/chewy/stash.rb +19 -30
  77. data/lib/chewy/strategy/active_job.rb +1 -1
  78. data/lib/chewy/strategy/atomic_no_refresh.rb +18 -0
  79. data/lib/chewy/strategy/base.rb +10 -0
  80. data/lib/chewy/strategy/delayed_sidekiq/scheduler.rb +168 -0
  81. data/lib/chewy/strategy/delayed_sidekiq/worker.rb +76 -0
  82. data/lib/chewy/strategy/delayed_sidekiq.rb +30 -0
  83. data/lib/chewy/strategy/lazy_sidekiq.rb +64 -0
  84. data/lib/chewy/strategy/sidekiq.rb +2 -1
  85. data/lib/chewy/strategy.rb +6 -19
  86. data/lib/chewy/version.rb +1 -1
  87. data/lib/chewy.rb +39 -86
  88. data/lib/generators/chewy/install_generator.rb +1 -1
  89. data/lib/tasks/chewy.rake +36 -32
  90. data/migration_guide.md +46 -8
  91. data/spec/chewy/config_spec.rb +16 -41
  92. data/spec/chewy/elastic_client_spec.rb +26 -0
  93. data/spec/chewy/fields/base_spec.rb +432 -147
  94. data/spec/chewy/fields/root_spec.rb +20 -28
  95. data/spec/chewy/fields/time_fields_spec.rb +5 -5
  96. data/spec/chewy/index/actions_spec.rb +368 -59
  97. data/spec/chewy/{type → index}/adapter/active_record_spec.rb +156 -40
  98. data/spec/chewy/{type → index}/adapter/object_spec.rb +21 -6
  99. data/spec/chewy/index/aliases_spec.rb +3 -3
  100. data/spec/chewy/index/import/bulk_builder_spec.rb +494 -0
  101. data/spec/chewy/{type → index}/import/bulk_request_spec.rb +5 -12
  102. data/spec/chewy/{type → index}/import/journal_builder_spec.rb +9 -19
  103. data/spec/chewy/{type → index}/import/routine_spec.rb +19 -19
  104. data/spec/chewy/{type → index}/import_spec.rb +164 -98
  105. data/spec/chewy/index/mapping_spec.rb +135 -0
  106. data/spec/chewy/index/observe/active_record_methods_spec.rb +68 -0
  107. data/spec/chewy/index/observe/callback_spec.rb +139 -0
  108. data/spec/chewy/index/observe_spec.rb +143 -0
  109. data/spec/chewy/index/settings_spec.rb +3 -1
  110. data/spec/chewy/index/specification_spec.rb +20 -30
  111. data/spec/chewy/{type → index}/syncer_spec.rb +14 -19
  112. data/spec/chewy/{type → index}/witchcraft_spec.rb +20 -22
  113. data/spec/chewy/index/wrapper_spec.rb +100 -0
  114. data/spec/chewy/index_spec.rb +60 -105
  115. data/spec/chewy/journal_spec.rb +25 -74
  116. data/spec/chewy/minitest/helpers_spec.rb +123 -15
  117. data/spec/chewy/minitest/search_index_receiver_spec.rb +28 -30
  118. data/spec/chewy/multi_search_spec.rb +4 -5
  119. data/spec/chewy/rake_helper_spec.rb +315 -55
  120. data/spec/chewy/rspec/build_query_spec.rb +34 -0
  121. data/spec/chewy/rspec/helpers_spec.rb +61 -0
  122. data/spec/chewy/rspec/update_index_spec.rb +74 -71
  123. data/spec/chewy/runtime_spec.rb +2 -2
  124. data/spec/chewy/search/loader_spec.rb +19 -53
  125. data/spec/chewy/search/pagination/kaminari_examples.rb +4 -6
  126. data/spec/chewy/search/pagination/kaminari_spec.rb +2 -2
  127. data/spec/chewy/search/parameters/collapse_spec.rb +5 -0
  128. data/spec/chewy/search/parameters/ignore_unavailable_spec.rb +67 -0
  129. data/spec/chewy/search/parameters/indices_spec.rb +26 -117
  130. data/spec/chewy/search/parameters/knn_spec.rb +5 -0
  131. data/spec/chewy/search/parameters/order_spec.rb +18 -11
  132. data/spec/chewy/search/parameters/query_storage_examples.rb +67 -21
  133. data/spec/chewy/search/parameters/search_after_spec.rb +4 -1
  134. data/spec/chewy/search/parameters/source_spec.rb +8 -2
  135. data/spec/chewy/search/parameters/track_total_hits_spec.rb +5 -0
  136. data/spec/chewy/search/parameters_spec.rb +18 -4
  137. data/spec/chewy/search/query_proxy_spec.rb +68 -17
  138. data/spec/chewy/search/request_spec.rb +292 -110
  139. data/spec/chewy/search/response_spec.rb +12 -12
  140. data/spec/chewy/search/scrolling_spec.rb +10 -17
  141. data/spec/chewy/search_spec.rb +40 -34
  142. data/spec/chewy/stash_spec.rb +9 -21
  143. data/spec/chewy/strategy/active_job_spec.rb +16 -16
  144. data/spec/chewy/strategy/atomic_no_refresh_spec.rb +60 -0
  145. data/spec/chewy/strategy/atomic_spec.rb +9 -10
  146. data/spec/chewy/strategy/delayed_sidekiq_spec.rb +208 -0
  147. data/spec/chewy/strategy/lazy_sidekiq_spec.rb +214 -0
  148. data/spec/chewy/strategy/sidekiq_spec.rb +12 -12
  149. data/spec/chewy/strategy_spec.rb +19 -15
  150. data/spec/chewy_spec.rb +24 -107
  151. data/spec/spec_helper.rb +3 -22
  152. data/spec/support/active_record.rb +25 -7
  153. metadata +78 -339
  154. data/.circleci/config.yml +0 -240
  155. data/Appraisals +0 -81
  156. data/gemfiles/rails.5.2.activerecord.gemfile +0 -17
  157. data/gemfiles/rails.5.2.mongoid.6.4.gemfile +0 -17
  158. data/gemfiles/rails.6.0.activerecord.gemfile +0 -17
  159. data/gemfiles/sequel.4.45.gemfile +0 -11
  160. data/lib/chewy/backports/deep_dup.rb +0 -46
  161. data/lib/chewy/backports/duplicable.rb +0 -91
  162. data/lib/chewy/search/pagination/will_paginate.rb +0 -43
  163. data/lib/chewy/search/parameters/types.rb +0 -20
  164. data/lib/chewy/strategy/resque.rb +0 -27
  165. data/lib/chewy/strategy/shoryuken.rb +0 -40
  166. data/lib/chewy/type/actions.rb +0 -43
  167. data/lib/chewy/type/adapter/mongoid.rb +0 -67
  168. data/lib/chewy/type/adapter/sequel.rb +0 -93
  169. data/lib/chewy/type/crutch.rb +0 -32
  170. data/lib/chewy/type/import/bulk_builder.rb +0 -122
  171. data/lib/chewy/type/observe.rb +0 -82
  172. data/lib/chewy/type.rb +0 -120
  173. data/lib/sequel/plugins/chewy_observe.rb +0 -63
  174. data/spec/chewy/search/pagination/will_paginate_examples.rb +0 -63
  175. data/spec/chewy/search/pagination/will_paginate_spec.rb +0 -23
  176. data/spec/chewy/search/parameters/types_spec.rb +0 -5
  177. data/spec/chewy/strategy/resque_spec.rb +0 -46
  178. data/spec/chewy/strategy/shoryuken_spec.rb +0 -70
  179. data/spec/chewy/type/actions_spec.rb +0 -50
  180. data/spec/chewy/type/adapter/mongoid_spec.rb +0 -372
  181. data/spec/chewy/type/adapter/sequel_spec.rb +0 -472
  182. data/spec/chewy/type/import/bulk_builder_spec.rb +0 -194
  183. data/spec/chewy/type/mapping_spec.rb +0 -175
  184. data/spec/chewy/type/observe_spec.rb +0 -137
  185. data/spec/chewy/type/wrapper_spec.rb +0 -100
  186. data/spec/chewy/type_spec.rb +0 -55
  187. data/spec/support/mongoid.rb +0 -93
  188. data/spec/support/sequel.rb +0 -80
@@ -1,175 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Chewy::Type::Mapping do
4
- let(:product) { ProductsIndex::Product }
5
- let(:review) { ReviewsIndex::Review }
6
-
7
- before do
8
- stub_index(:products) do
9
- define_type :product do
10
- root do
11
- field :name, 'surname'
12
- field :title, type: 'text' do
13
- field :subfield1
14
- end
15
- field 'price', type: 'float' do
16
- field :subfield2
17
- end
18
- agg :named_agg do
19
- {avg: {field: 'title.subfield1'}}
20
- end
21
- end
22
- end
23
- end
24
- stub_index(:reviews) do
25
- define_type :review do
26
- field :title, :body
27
- field :comments do
28
- field :message
29
- field :rating, type: 'long'
30
- end
31
- agg :named_agg do
32
- {avg: {field: 'comments.rating'}}
33
- end
34
- end
35
- end
36
- end
37
-
38
- context 'no root element call' do
39
- before do
40
- stub_index(:products) do
41
- define_type :product do
42
- field :title, type: 'text' do
43
- field :subfield1
44
- end
45
- end
46
- end
47
- end
48
-
49
- specify { expect(product.root.children.map(&:name)).to eq([:title]) }
50
- specify { expect(product.root.children.map(&:parent)).to eq([product.root]) }
51
- specify { expect(product.root.children[0].children.map(&:name)).to eq([:subfield1]) }
52
- specify { expect(product.root.children[0].children.map(&:parent)).to eq([product.root.children[0]]) }
53
-
54
- context 'default root options are set' do
55
- around do |example|
56
- previous_options = Chewy.default_root_options
57
- Chewy.default_root_options = {_all: {enabled: false}}
58
- example.run
59
- Chewy.default_root_options = previous_options
60
- end
61
-
62
- specify { expect(product.mappings_hash[:product]).to include(_all: {enabled: false}) }
63
- end
64
- end
65
-
66
- describe '.agg' do
67
- specify { expect(product._agg_defs[:named_agg].call).to eq(avg: {field: 'title.subfield1'}) }
68
- specify { expect(review._agg_defs[:named_agg].call).to eq(avg: {field: 'comments.rating'}) }
69
- end
70
-
71
- describe '.field' do
72
- specify { expect(product.root.children.map(&:name)).to eq(%i[name surname title price]) }
73
- specify { expect(product.root.children.map(&:parent)).to eq([product.root] * 4) }
74
-
75
- specify { expect(product.root.children[0].children.map(&:name)).to eq([]) }
76
- specify { expect(product.root.children[1].children.map(&:name)).to eq([]) }
77
-
78
- specify { expect(product.root.children[2].children.map(&:name)).to eq([:subfield1]) }
79
- specify { expect(product.root.children[2].children.map(&:parent)).to eq([product.root.children[2]]) }
80
-
81
- specify { expect(product.root.children[3].children.map(&:name)).to eq([:subfield2]) }
82
- specify { expect(product.root.children[3].children.map(&:parent)).to eq([product.root.children[3]]) }
83
- end
84
-
85
- describe '.mappings_hash' do
86
- specify { expect(product.mappings_hash).to eq(product.root.mappings_hash) }
87
-
88
- context 'root merging' do
89
- context do
90
- before do
91
- stub_index(:products) do
92
- define_type :product do
93
- root _parent: 'project', other_option: 'nothing' do
94
- field :name do
95
- field :last_name # will be redefined in the following root flock
96
- end
97
- end
98
- root _parent: 'something_else'
99
- root other_option: 'option_value' do
100
- field :identifier
101
- field :name, type: 'integer'
102
- end
103
- end
104
- end
105
- end
106
-
107
- specify do
108
- expect(product.mappings_hash).to eq(product: {
109
- properties: {
110
- name: {type: 'integer'},
111
- identifier: {type: Chewy.default_field_type}
112
- },
113
- other_option: 'option_value',
114
- _parent: {type: 'something_else'}
115
- })
116
- end
117
- end
118
- end
119
-
120
- context 'parent-child relationship' do
121
- context do
122
- before do
123
- stub_index(:products) do
124
- define_type :product do
125
- root _parent: 'project', parent_id: -> { project_id } do
126
- field :name, 'surname'
127
- end
128
- end
129
- end
130
- end
131
-
132
- specify { expect(product.mappings_hash[:product][:_parent]).to eq(type: 'project') }
133
- end
134
-
135
- context do
136
- before do
137
- stub_index(:products) do
138
- define_type :product do
139
- root parent: {'type' => 'project'}, parent_id: -> { project_id } do
140
- field :name, 'surname'
141
- end
142
- end
143
- end
144
- end
145
-
146
- specify { expect(product.mappings_hash[:product][:_parent]).to eq('type' => 'project') }
147
- end
148
- end
149
- end
150
-
151
- describe '.supports_outdated_sync?' do
152
- def type(&block)
153
- stub_index(:cities) do
154
- define_type :city, &block
155
- end
156
- CitiesIndex::City
157
- end
158
-
159
- specify { expect(type.supports_outdated_sync?).to eq(false) }
160
- specify { expect(type { field :updated_at }.supports_outdated_sync?).to eq(true) }
161
- specify { expect(type { field :updated_at, value: -> {} }.supports_outdated_sync?).to eq(false) }
162
- specify do
163
- expect(type do
164
- self.outdated_sync_field = :version
165
- field :updated_at
166
- end.supports_outdated_sync?).to eq(false)
167
- end
168
- specify do
169
- expect(type do
170
- self.outdated_sync_field = :version
171
- field :version
172
- end.supports_outdated_sync?).to eq(true)
173
- end
174
- end
175
- end
@@ -1,137 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Chewy::Type::Observe do
4
- describe '.update_index' do
5
- before do
6
- stub_index(:dummies) do
7
- define_type :dummy
8
- end
9
- end
10
-
11
- let(:backreferenced) { Array.new(3) { |i| double(id: i) } }
12
-
13
- specify do
14
- expect { DummiesIndex::Dummy.update_index(backreferenced) }
15
- .to raise_error Chewy::UndefinedUpdateStrategy
16
- end
17
- specify do
18
- expect { DummiesIndex::Dummy.update_index([]) }
19
- .not_to update_index('dummies#dummy')
20
- end
21
- specify do
22
- expect { DummiesIndex::Dummy.update_index(nil) }
23
- .not_to update_index('dummies#dummy')
24
- end
25
- end
26
-
27
- context 'integration', :orm do
28
- let(:update_condition) { true }
29
-
30
- before do
31
- city_countries_update_proc = if adapter == :sequel
32
- ->(*) { previous_changes.try(:[], :country_id) || country }
33
- else
34
- ->(*) { changes['country_id'] || previous_changes['country_id'] || country }
35
- end
36
-
37
- stub_model(:city) do
38
- update_index(->(city) { "cities##{city.class.name.underscore}" }) { self }
39
- update_index 'countries#country', &city_countries_update_proc
40
- end
41
-
42
- stub_model(:country) do
43
- update_index('cities#city', if: -> { update_condition }) { cities }
44
- update_index(-> { "countries##{self.class.name.underscore}" }, :self)
45
- attr_accessor :update_condition
46
- end
47
-
48
- if adapter == :sequel
49
- City.many_to_one :country
50
- Country.one_to_many :cities
51
- City.plugin :dirty
52
- else
53
- if adapter == :mongoid && Mongoid::VERSION.start_with?('6')
54
- City.belongs_to :country, optional: true
55
- else
56
- City.belongs_to :country
57
- end
58
- Country.has_many :cities
59
- end
60
-
61
- stub_index(:cities) do
62
- define_type City
63
- end
64
-
65
- stub_index(:countries) do
66
- define_type Country
67
- end
68
- end
69
-
70
- context do
71
- let!(:country1) { Chewy.strategy(:atomic) { Country.create!(id: 1, update_condition: update_condition) } }
72
- let!(:country2) { Chewy.strategy(:atomic) { Country.create!(id: 2, update_condition: update_condition) } }
73
- let!(:city) { Chewy.strategy(:atomic) { City.create!(id: 1, country: country1) } }
74
-
75
- specify { expect { city.save! }.to update_index('cities#city').and_reindex(city).only }
76
- specify { expect { city.save! }.to update_index('countries#country').and_reindex(country1).only }
77
-
78
- specify { expect { city.update!(country: nil) }.to update_index('cities#city').and_reindex(city).only }
79
- specify { expect { city.update!(country: nil) }.to update_index('countries#country').and_reindex(country1).only }
80
-
81
- specify { expect { city.update!(country: country2) }.to update_index('cities#city').and_reindex(city).only }
82
- specify { expect { city.update!(country: country2) }.to update_index('countries#country').and_reindex(country1, country2).only }
83
- end
84
-
85
- context do
86
- let!(:country) do
87
- Chewy.strategy(:atomic) do
88
- cities = Array.new(2) { |i| City.create!(id: i) }
89
- if adapter == :sequel
90
- Country.create(id: 1, update_condition: update_condition).tap do |country|
91
- cities.each { |city| country.add_city(city) }
92
- end
93
- else
94
- Country.create!(id: 1, cities: cities, update_condition: update_condition)
95
- end
96
- end
97
- end
98
-
99
- specify { expect { country.save! }.to update_index('cities#city').and_reindex(country.cities).only }
100
- specify { expect { country.save! }.to update_index('countries#country').and_reindex(country).only }
101
-
102
- context 'conditional update' do
103
- let(:update_condition) { false }
104
- specify { expect { country.save! }.not_to update_index('cities#city') }
105
- end
106
- end
107
- end
108
-
109
- context 'transactions', :active_record do
110
- context do
111
- before { stub_model(:city) { update_index 'cities#city', :self } }
112
- before { stub_index(:cities) { define_type City } }
113
-
114
- specify do
115
- Chewy.strategy(:urgent) do
116
- ActiveRecord::Base.transaction do
117
- expect { City.create! }.not_to update_index('cities#city')
118
- end
119
- end
120
- end
121
- end
122
-
123
- context do
124
- before { allow(Chewy).to receive_messages(use_after_commit_callbacks: false) }
125
- before { stub_model(:city) { update_index 'cities#city', :self } }
126
- before { stub_index(:cities) { define_type City } }
127
-
128
- specify do
129
- Chewy.strategy(:urgent) do
130
- ActiveRecord::Base.transaction do
131
- expect { City.create! }.to update_index('cities#city')
132
- end
133
- end
134
- end
135
- end
136
- end
137
- end
@@ -1,100 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Chewy::Type::Wrapper do
4
- before do
5
- stub_class(:city)
6
- stub_index(:cities) do
7
- define_type City
8
- end
9
- end
10
-
11
- let(:city_type) { CitiesIndex::City }
12
-
13
- describe '.build' do
14
- specify do
15
- expect(city_type.build({}).attributes)
16
- .to eq('id' => nil, '_score' => nil, '_explanation' => nil)
17
- end
18
- specify do
19
- expect(city_type.build('_source' => {name: 'Martin'}).attributes)
20
- .to eq('id' => nil, '_score' => nil, '_explanation' => nil, 'name' => 'Martin')
21
- end
22
- specify do
23
- expect(city_type.build('_id' => 42).attributes)
24
- .to eq('id' => 42, '_score' => nil, '_explanation' => nil)
25
- end
26
- specify do
27
- expect(city_type.build('_id' => 42, '_source' => {'id' => 43}).attributes)
28
- .to eq('id' => 43, '_score' => nil, '_explanation' => nil)
29
- end
30
- specify do
31
- expect(city_type.build('_score' => 42, '_explanation' => {foo: 'bar'}).attributes)
32
- .to eq('id' => nil, '_score' => 42, '_explanation' => {foo: 'bar'})
33
- end
34
- specify do
35
- expect(city_type.build('_score' => 42, 'borogoves' => {foo: 'bar'})._data)
36
- .to eq('_score' => 42, 'borogoves' => {foo: 'bar'})
37
- end
38
- end
39
-
40
- describe '#initialize' do
41
- subject(:city) { city_type.new(name: 'Martin', age: 42) }
42
-
43
- it do
44
- is_expected.to respond_to(:name)
45
- .and respond_to(:age)
46
- .and have_attributes(
47
- name: 'Martin',
48
- age: 42
49
- )
50
- end
51
-
52
- it { expect { city.population }.to raise_error(NoMethodError) }
53
-
54
- context 'highlight' do
55
- subject(:city) do
56
- city_type.new(name: 'Martin', age: 42)
57
- .tap do |city|
58
- city._data = {
59
- 'highlight' => {'name' => ['<b>Mar</b>tin']}
60
- }
61
- end
62
- end
63
-
64
- it do
65
- is_expected.to respond_to(:name_highlight)
66
- .and respond_to(:name_highlights)
67
- .and have_attributes(
68
- name: 'Martin',
69
- name_highlight: '<b>Mar</b>tin',
70
- name_highlights: ['<b>Mar</b>tin']
71
- )
72
- end
73
- end
74
- end
75
-
76
- describe '#==' do
77
- specify { expect(city_type.new(id: 42)).to eq(city_type.new(id: 42)) }
78
- specify { expect(city_type.new(id: 42, age: 55)).to eq(city_type.new(id: 42, age: 54)) }
79
- specify { expect(city_type.new(id: 42)).not_to eq(city_type.new(id: 43)) }
80
- specify { expect(city_type.new(id: 42, age: 55)).not_to eq(city_type.new(id: 43, age: 55)) }
81
- specify { expect(city_type.new(age: 55)).to eq(city_type.new(age: 55)) }
82
- specify { expect(city_type.new(age: 55)).not_to eq(city_type.new(age: 54)) }
83
-
84
- specify { expect(city_type.new(id: '42')).to eq(City.new.tap { |m| allow(m).to receive_messages(id: 42) }) }
85
- specify { expect(city_type.new(id: 42)).not_to eq(City.new.tap { |m| allow(m).to receive_messages(id: 43) }) }
86
- specify { expect(city_type.new(id: 42)).not_to eq(Class.new) }
87
-
88
- context 'models', :orm do
89
- before do
90
- stub_model(:city)
91
- stub_index(:cities) do
92
- define_type City
93
- end
94
- end
95
- specify { expect(city_type.new(id: '42')).to eq(City.new.tap { |m| allow(m).to receive_messages(id: 42) }) }
96
- specify { expect(city_type.new(id: 42)).not_to eq(City.new.tap { |m| allow(m).to receive_messages(id: 43) }) }
97
- specify { expect(city_type.new(id: 42)).not_to eq(Class.new) }
98
- end
99
- end
100
- end
@@ -1,55 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Chewy::Type do
4
- describe '.derivable_name' do
5
- specify { expect { Class.new(Chewy::Type).derivable_name }.to raise_error NotImplementedError }
6
-
7
- specify do
8
- index = Class.new(Chewy::Index) { define_type :city }
9
- expect(index::City.derivable_name).to be_nil
10
- end
11
-
12
- specify do
13
- stub_index(:places) { define_type :city }
14
- expect(PlacesIndex::City.derivable_name).to eq('places#city')
15
- end
16
-
17
- specify do
18
- stub_index('namespace/places') { define_type :city }
19
- expect(Namespace::PlacesIndex::City.derivable_name).to eq('namespace/places#city')
20
- end
21
- end
22
-
23
- describe '.types' do
24
- subject { Class.new(Chewy::Type) }
25
- specify { expect(subject.types).to eq([subject]) }
26
- end
27
-
28
- describe '.scopes' do
29
- before do
30
- stub_index(:places) do
31
- def self.by_id; end
32
-
33
- define_type :city do
34
- def self.by_rating; end
35
-
36
- def self.by_name; end
37
- end
38
- end
39
- end
40
-
41
- specify { expect(described_class.scopes).to eq([]) }
42
- specify { expect(PlacesIndex::City.scopes).to match_array(%i[by_rating by_name]) }
43
- specify { expect { PlacesIndex::City.non_existing_method_call }.to raise_error(NoMethodError) }
44
-
45
- specify { expect(PlacesIndex::City._default_import_options).to eq({}) }
46
- specify { expect { PlacesIndex::City.default_import_options(invalid_option: 'Yeah!') }.to raise_error(ArgumentError) }
47
-
48
- context 'default_import_options is set' do
49
- let(:converter) { -> {} }
50
- before { PlacesIndex::City.default_import_options(batch_size: 500, raw_import: converter) }
51
-
52
- specify { expect(PlacesIndex::City._default_import_options).to eq(batch_size: 500, raw_import: converter) }
53
- end
54
- end
55
- end
@@ -1,93 +0,0 @@
1
- require 'database_cleaner'
2
-
3
- CONFIG = {
4
- sessions: {
5
- default: {
6
- uri: 'mongodb://127.0.0.1:27017/chewy_mongoid_test'
7
- }
8
- },
9
- clients: {
10
- default: {
11
- uri: 'mongodb://127.0.0.1:27017/chewy_mongoid_test'
12
- }
13
- }
14
- }.freeze
15
-
16
- Mongoid.configure do |config|
17
- config.load_configuration(CONFIG)
18
- end
19
-
20
- Mongoid.logger = Logger.new('/dev/null')
21
-
22
- module MongoidClassHelpers
23
- extend ActiveSupport::Concern
24
-
25
- module Document
26
- def serializable_hash(options = nil)
27
- hash = super(options)
28
- hash['id'] = hash.delete('_id') if hash.key?('_id')
29
- hash
30
- end
31
- end
32
-
33
- module Country
34
- extend ActiveSupport::Concern
35
-
36
- included do
37
- include Mongoid::Document
38
- include Mongoid::Timestamps::Updated
39
- include Document
40
-
41
- field :name, type: String
42
- field :country_code, type: String
43
- field :rating, type: Integer
44
- end
45
- end
46
-
47
- module City
48
- extend ActiveSupport::Concern
49
-
50
- included do
51
- include Mongoid::Document
52
- include Mongoid::Timestamps::Updated
53
- include Document
54
-
55
- field :name, type: String
56
- field :rating, type: Integer
57
- end
58
- end
59
-
60
- def adapter
61
- :mongoid
62
- end
63
-
64
- def stub_model(name, superclass = nil, &block)
65
- mixin = "MongoidClassHelpers::#{name.to_s.camelize}".safe_constantize || Mongoid::Document
66
-
67
- model = stub_class(name, superclass) do
68
- include mixin
69
- store_in collection: name.to_s.tableize
70
- end
71
- model.tap { |i| i.class_eval(&block) if block }
72
- end
73
- end
74
-
75
- RSpec.configure do |config|
76
- config.include MongoidClassHelpers
77
-
78
- config.filter_run_excluding :active_record
79
- config.filter_run_excluding :sequel
80
-
81
- config.before(:suite) do
82
- DatabaseCleaner.clean_with :truncation
83
- DatabaseCleaner.strategy = :truncation
84
- end
85
-
86
- config.before do
87
- DatabaseCleaner.start
88
- end
89
-
90
- config.after do
91
- DatabaseCleaner.clean
92
- end
93
- end
@@ -1,80 +0,0 @@
1
- require 'database_cleaner'
2
-
3
- DB = Sequel.sqlite # logger: Logger.new(STDERR)
4
- Sequel::Deprecation.output = false
5
-
6
- DB.create_table :countries do
7
- primary_key :id
8
- column :name, :string
9
- column :country_code, :string
10
- column :rating, :integer
11
- column :updated_at, :datetime
12
- end
13
-
14
- DB.create_table :cities do
15
- primary_key :id
16
- column :country_id, :integer
17
- column :name, :string
18
- column :rating, :integer
19
- column :updated_at, :datetime
20
- end
21
-
22
- DB.create_table :rating_cities do
23
- primary_key :rating
24
- column :country_id, :integer
25
- column :name, :string
26
- column :updated_at, :datetime
27
- end
28
-
29
- Sequel::Model.plugin :timestamps, update_on_create: true
30
- Sequel::Model.plugin :chewy_observe
31
-
32
- module SequelClassHelpers
33
- extend ActiveSupport::Concern
34
-
35
- class AdaptedSequelModel < Sequel::Model
36
- # Allow to set primary key using mass assignment.
37
- unrestrict_primary_key
38
-
39
- # Aliases for compatibility with specs that were written with ActiveRecord in mind...
40
- alias_method :save!, :save
41
- alias_method :update_attributes, :update
42
- alias_method :update_attributes!, :update
43
-
44
- class << self
45
- alias_method :create!, :create
46
- end
47
- end
48
-
49
- def adapter
50
- :sequel
51
- end
52
-
53
- def stub_model(name, &block)
54
- stub_class(name, AdaptedSequelModel, &block).tap do |klass|
55
- # Sequel doesn't work well with dynamically created classes,
56
- # so we must set the dataset (table) name manually.
57
- klass.dataset = name.to_s.pluralize.to_sym
58
- end
59
- end
60
- end
61
-
62
- RSpec.configure do |config|
63
- config.include SequelClassHelpers
64
-
65
- config.filter_run_excluding :active_record
66
- config.filter_run_excluding :mongoid
67
-
68
- config.before(:suite) do
69
- DatabaseCleaner.clean_with :truncation
70
- DatabaseCleaner.strategy = :truncation
71
- end
72
-
73
- config.before do
74
- DatabaseCleaner.start
75
- end
76
-
77
- config.after do
78
- DatabaseCleaner.clean
79
- end
80
- end