mongoid-history 0.8.3 → 0.8.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -1
  3. data/.document +5 -5
  4. data/.github/workflows/test.yml +72 -0
  5. data/.gitignore +46 -46
  6. data/.rspec +2 -2
  7. data/.rubocop.yml +6 -6
  8. data/.rubocop_todo.yml +99 -99
  9. data/CHANGELOG.md +173 -163
  10. data/CONTRIBUTING.md +117 -118
  11. data/Dangerfile +1 -1
  12. data/Gemfile +49 -40
  13. data/LICENSE.txt +20 -20
  14. data/README.md +609 -608
  15. data/RELEASING.md +66 -67
  16. data/Rakefile +24 -24
  17. data/UPGRADING.md +53 -53
  18. data/lib/mongoid/history/attributes/base.rb +72 -72
  19. data/lib/mongoid/history/attributes/create.rb +45 -45
  20. data/lib/mongoid/history/attributes/destroy.rb +34 -34
  21. data/lib/mongoid/history/attributes/update.rb +104 -104
  22. data/lib/mongoid/history/options.rb +177 -177
  23. data/lib/mongoid/history/trackable.rb +588 -583
  24. data/lib/mongoid/history/tracker.rb +247 -247
  25. data/lib/mongoid/history/version.rb +5 -5
  26. data/lib/mongoid/history.rb +77 -77
  27. data/lib/mongoid-history.rb +1 -1
  28. data/mongoid-history.gemspec +25 -25
  29. data/perf/benchmark_modified_attributes_for_create.rb +65 -65
  30. data/perf/gc_suite.rb +21 -21
  31. data/spec/integration/embedded_in_polymorphic_spec.rb +112 -112
  32. data/spec/integration/integration_spec.rb +976 -976
  33. data/spec/integration/multi_relation_spec.rb +47 -47
  34. data/spec/integration/multiple_trackers_spec.rb +68 -68
  35. data/spec/integration/nested_embedded_documents_spec.rb +64 -64
  36. data/spec/integration/nested_embedded_documents_tracked_in_parent_spec.rb +124 -124
  37. data/spec/integration/nested_embedded_polymorphic_documents_spec.rb +115 -115
  38. data/spec/integration/subclasses_spec.rb +47 -47
  39. data/spec/integration/track_history_order_spec.rb +84 -84
  40. data/spec/integration/validation_failure_spec.rb +76 -76
  41. data/spec/spec_helper.rb +32 -30
  42. data/spec/support/error_helpers.rb +7 -0
  43. data/spec/support/mongoid.rb +11 -11
  44. data/spec/support/mongoid_history.rb +12 -12
  45. data/spec/unit/attributes/base_spec.rb +141 -141
  46. data/spec/unit/attributes/create_spec.rb +342 -342
  47. data/spec/unit/attributes/destroy_spec.rb +228 -228
  48. data/spec/unit/attributes/update_spec.rb +342 -342
  49. data/spec/unit/callback_options_spec.rb +165 -165
  50. data/spec/unit/embedded_methods_spec.rb +87 -87
  51. data/spec/unit/history_spec.rb +58 -58
  52. data/spec/unit/my_instance_methods_spec.rb +555 -555
  53. data/spec/unit/options_spec.rb +365 -365
  54. data/spec/unit/singleton_methods_spec.rb +406 -406
  55. data/spec/unit/store/default_store_spec.rb +11 -11
  56. data/spec/unit/store/request_store_spec.rb +13 -13
  57. data/spec/unit/trackable_spec.rb +1057 -987
  58. data/spec/unit/tracker_spec.rb +190 -190
  59. metadata +9 -7
  60. data/.travis.yml +0 -36
@@ -1,365 +1,365 @@
1
- require 'spec_helper'
2
-
3
- describe Mongoid::History::Options do
4
- before :each do
5
- class ModelOne
6
- include Mongoid::Document
7
- include Mongoid::History::Trackable
8
-
9
- store_in collection: :model_ones
10
-
11
- field :foo
12
- field :b, as: :bar
13
-
14
- if Mongoid::Compatibility::Version.mongoid7_or_newer?
15
- embeds_one :emb_one
16
- embeds_one :emb_two, store_as: :emtw
17
- embeds_many :emb_threes
18
- embeds_many :emb_fours, store_as: :emfs
19
- else
20
- embeds_one :emb_one, inverse_class_name: 'EmbOne'
21
- embeds_one :emb_two, store_as: :emtw, inverse_class_name: 'EmbTwo'
22
- embeds_many :emb_threes, inverse_class_name: 'EmbThree'
23
- embeds_many :emb_fours, store_as: :emfs, inverse_class_name: 'EmbFour'
24
- end
25
-
26
- track_history
27
- end
28
-
29
- class EmbOne
30
- include Mongoid::Document
31
-
32
- field :f_em_foo
33
- field :fmb, as: :f_em_bar
34
-
35
- embedded_in :model_one
36
- end
37
-
38
- class EmbTwo
39
- include Mongoid::Document
40
-
41
- field :f_em_baz
42
- embedded_in :model_one
43
- end
44
-
45
- class EmbThree
46
- include Mongoid::Document
47
-
48
- field :f_em_foo
49
- field :fmb, as: :f_em_bar
50
-
51
- embedded_in :model_one
52
- end
53
-
54
- class EmbFour
55
- include Mongoid::Document
56
-
57
- field :f_em_baz
58
- embedded_in :model_one
59
- end
60
- end
61
-
62
- after :each do
63
- Object.send(:remove_const, :ModelOne)
64
- Object.send(:remove_const, :EmbOne)
65
- Object.send(:remove_const, :EmbTwo)
66
- Object.send(:remove_const, :EmbThree)
67
- Object.send(:remove_const, :EmbFour)
68
- end
69
-
70
- let(:options) { {} }
71
- let(:service) { described_class.new(ModelOne, options) }
72
-
73
- subject { service }
74
-
75
- it { is_expected.to respond_to :trackable }
76
- it { is_expected.to respond_to :options }
77
-
78
- describe '#initialize' do
79
- it { expect(service.trackable).to eq ModelOne }
80
- end
81
-
82
- describe '#scope' do
83
- it { expect(service.scope).to eq :model_one }
84
- end
85
-
86
- describe '#parse' do
87
- it 'does not mutate the original options' do
88
- original_options = service.options.dup
89
- service.prepared
90
- expect(service.options).to eq original_options
91
- end
92
-
93
- describe '#default_options' do
94
- let(:expected_options) do
95
- {
96
- on: :all,
97
- except: %i[created_at updated_at],
98
- tracker_class_name: nil,
99
- modifier_field: :modifier,
100
- version_field: :version,
101
- changes_method: :changes,
102
- scope: :model_one,
103
- track_create: true,
104
- track_update: true,
105
- track_destroy: true,
106
- format: nil
107
- }
108
- end
109
- it { expect(service.send(:default_options)).to eq expected_options }
110
- end
111
-
112
- describe '#prepare_skipped_fields' do
113
- let(:options) { { except: value } }
114
- subject { service.prepared }
115
-
116
- context 'with field' do
117
- let(:value) { :foo }
118
- it { expect(subject[:except]).to eq %w[foo] }
119
- end
120
-
121
- context 'with array of fields' do
122
- let(:value) { %i[foo] }
123
- it { expect(subject[:except]).to eq %w[foo] }
124
- end
125
-
126
- context 'with field alias' do
127
- let(:value) { %i[foo bar] }
128
- it { expect(subject[:except]).to eq %w[foo b] }
129
- end
130
-
131
- context 'with duplicate values' do
132
- let(:value) { %i[foo bar b] }
133
- it { expect(subject[:except]).to eq %w[foo b] }
134
- end
135
-
136
- context 'with blank values' do
137
- let(:value) { %i[foo] | [nil] }
138
- it { expect(subject[:except]).to eq %w[foo] }
139
- end
140
- end
141
-
142
- describe '#prepare_formatted_fields' do
143
- let(:options) { { format: value } }
144
- subject { service.prepared }
145
-
146
- context 'with non-hash' do
147
- let(:value) { :foo }
148
- it { expect(subject[:format]).to eq({}) }
149
- end
150
-
151
- context 'with a field format' do
152
- let(:value) { { foo: '&&&' } }
153
- it { expect(subject[:format]).to include 'foo' => '&&&' }
154
- end
155
-
156
- context 'with nested format' do
157
- let(:value) { { emb_one: { f_em_foo: '***' } } }
158
- it { expect(subject[:format]).to include 'emb_one' => { 'f_em_foo' => '***' } }
159
- end
160
- end
161
-
162
- describe '#parse_tracked_fields_and_relations' do
163
- context 'when options not passed' do
164
- let(:expected_options) do
165
- {
166
- on: %i[foo b],
167
- except: %w[created_at updated_at],
168
- tracker_class_name: nil,
169
- modifier_field: :modifier,
170
- version_field: :version,
171
- changes_method: :changes,
172
- scope: :model_one,
173
- track_create: true,
174
- track_update: true,
175
- track_destroy: true,
176
- fields: %w[foo b],
177
- dynamic: [],
178
- relations: { embeds_one: {}, embeds_many: {} },
179
- format: {}
180
- }
181
- end
182
- it { expect(service.prepared).to eq expected_options }
183
- end
184
-
185
- context 'when options passed' do
186
- subject { service.prepared }
187
-
188
- describe '@options' do
189
- let(:options) { { on: value } }
190
-
191
- context 'with field' do
192
- let(:value) { :foo }
193
- it { expect(subject[:on]).to eq %i[foo] }
194
- it { expect(subject[:fields]).to eq %w[foo] }
195
- end
196
-
197
- context 'with array of fields' do
198
- let(:value) { %i[foo] }
199
- it { expect(subject[:on]).to eq %i[foo] }
200
- it { expect(subject[:fields]).to eq %w[foo] }
201
- end
202
-
203
- context 'with embeds_one relation attributes' do
204
- let(:value) { { emb_one: %i[f_em_foo] } }
205
- it { expect(subject[:on]).to eq [[:emb_one, %i[f_em_foo]]] }
206
- end
207
-
208
- context 'with fields and embeds_one relation attributes' do
209
- let(:value) { [:foo, emb_one: %i[f_em_foo]] }
210
- it { expect(subject[:on]).to eq [:foo, emb_one: %i[f_em_foo]] }
211
- end
212
-
213
- context 'with :all' do
214
- let(:value) { :all }
215
- it { expect(subject[:on]).to eq %i[foo b] }
216
- end
217
-
218
- context 'with :fields' do
219
- let(:value) { :fields }
220
- it { expect(subject[:on]).to eq %i[foo b] }
221
- end
222
-
223
- describe '#categorize_tracked_option' do
224
- context 'with skipped field' do
225
- let(:options) { { on: %i[foo bar], except: :foo } }
226
- it { expect(subject[:fields]).to eq %w[b] }
227
- end
228
-
229
- context 'with skipped embeds_one relation' do
230
- let(:options) { { on: %i[fields emb_one emb_two], except: :emb_one } }
231
- it { expect(subject[:relations][:embeds_one]).to eq('emtw' => %w[_id f_em_baz]) }
232
- end
233
-
234
- context 'with skipped embeds_many relation' do
235
- let(:options) { { on: %i[fields emb_threes emb_fours], except: :emb_threes } }
236
- it { expect(subject[:relations][:embeds_many]).to eq('emfs' => %w[_id f_em_baz]) }
237
- end
238
-
239
- context 'with reserved field' do
240
- let(:options) { { on: %i[_id _type foo deleted_at] } }
241
- it { expect(subject[:fields]).to eq %w[foo] }
242
- end
243
-
244
- context 'when embeds_one attribute passed' do
245
- let(:options) { { on: { emb_one: :f_em_foo } } }
246
- it { expect(subject[:relations][:embeds_one]).to eq('emb_one' => %w[_id f_em_foo]) }
247
- end
248
-
249
- context 'when embeds_one attributes array passed' do
250
- let(:options) { { on: { emb_one: %i[f_em_foo] } } }
251
- it { expect(subject[:relations][:embeds_one]).to eq('emb_one' => %w[_id f_em_foo]) }
252
- end
253
-
254
- context 'when embeds_many attribute passed' do
255
- let(:options) { { on: { emb_threes: :f_em_foo } } }
256
- it { expect(subject[:relations][:embeds_many]).to eq('emb_threes' => %w[_id f_em_foo]) }
257
- end
258
-
259
- context 'when embeds_many attributes array passed' do
260
- let(:options) { { on: { emb_threes: %i[f_em_foo] } } }
261
- it { expect(subject[:relations][:embeds_many]).to eq('emb_threes' => %w[_id f_em_foo]) }
262
- end
263
-
264
- context 'when embeds_one attributes not passed' do
265
- let(:options) { { on: :emb_one } }
266
- it { expect(subject[:relations][:embeds_one]).to eq('emb_one' => %w[_id f_em_foo fmb]) }
267
- end
268
-
269
- context 'when embeds_many attributes not passed' do
270
- let(:options) { { on: :emb_threes } }
271
- it { expect(subject[:relations][:embeds_many]).to eq('emb_threes' => %w[_id f_em_foo fmb]) }
272
- end
273
-
274
- context 'when embeds_one attribute alias passed' do
275
- let(:options) { { on: { emb_one: %i[f_em_bar] } } }
276
- it { expect(subject[:relations][:embeds_one]).to eq('emb_one' => %w[_id fmb]) }
277
- end
278
-
279
- context 'when embeds_many attribute alias passed' do
280
- let(:options) { { on: { emb_threes: %i[f_em_bar] } } }
281
- it { expect(subject[:relations][:embeds_many]).to eq('emb_threes' => %w[_id fmb]) }
282
- end
283
-
284
- context 'with fields, and multiple embeds_one, and embeds_many relations' do
285
- let(:options) { { on: [:foo, :bar, :emb_two, { emb_threes: %i[f_em_foo f_em_bar], emb_fours: :f_em_baz }] } }
286
- it 'should categorize fields and associations correctly' do
287
- expect(subject[:fields]).to eq(%w[foo b])
288
- expect(subject[:relations][:embeds_one]).to eq('emtw' => %w[_id f_em_baz])
289
- expect(subject[:relations][:embeds_many]).to eq('emb_threes' => %w[_id f_em_foo fmb], 'emfs' => %w[_id f_em_baz])
290
- end
291
- end
292
-
293
- context 'with field alias' do
294
- let(:options) { { on: :bar } }
295
- it { expect(subject[:fields]).to eq %w[b] }
296
- end
297
-
298
- context 'with dynamic field name' do
299
- let(:options) { { on: :my_field } }
300
- it { expect(subject[:dynamic]).to eq %w[my_field] }
301
- end
302
-
303
- context 'with relations' do
304
- let(:options) { { on: :embedded_relations } }
305
- it do
306
- expect(subject[:relations]).to eq(
307
- embeds_many: { 'emb_threes' => %w[_id f_em_foo fmb],
308
- 'emfs' => %w[_id f_em_baz] },
309
- embeds_one: { 'emb_one' => %w[_id f_em_foo fmb],
310
- 'emtw' => %w[_id f_em_baz] }
311
- )
312
- end
313
- end
314
- end
315
- end
316
-
317
- describe ':modifier_field' do
318
- let(:options) { { modifier_field: :my_modifier_field } }
319
- it { expect(subject[:modifier_field]).to eq :my_modifier_field }
320
- end
321
-
322
- describe ':version_field' do
323
- let(:options) { { version_field: :my_version_field } }
324
- it { expect(subject[:version_field]).to eq :my_version_field }
325
- end
326
-
327
- describe ':paranoia_field' do
328
- let(:options) { { paranoia_field: :my_paranoia_field } }
329
- it { expect(subject[:paranoia_field]).to eq :my_paranoia_field }
330
- end
331
-
332
- describe ':changes_method' do
333
- let(:options) { { changes_method: :my_changes_method } }
334
- it { expect(subject[:changes_method]).to eq :my_changes_method }
335
- end
336
-
337
- describe ':scope' do
338
- let(:options) { { scope: :my_scope } }
339
- it { expect(subject[:scope]).to eq :my_scope }
340
- end
341
-
342
- describe ':track_create' do
343
- let(:options) { { track_create: true } }
344
- it { expect(subject[:track_create]).to be true }
345
- end
346
-
347
- describe ':track_update' do
348
- let(:options) { { track_update: false } }
349
- it { expect(subject[:track_update]).to be false }
350
- end
351
-
352
- describe ':track_destroy' do
353
- let(:options) { { track_destroy: true } }
354
- it { expect(subject[:track_destroy]).to be true }
355
- end
356
-
357
- describe '#remove_reserved_fields' do
358
- let(:options) { { on: %i[_id _type foo version modifier_id] } }
359
- it { expect(subject[:fields]).to eq %w[foo] }
360
- it { expect(subject[:dynamic]).to eq [] }
361
- end
362
- end
363
- end
364
- end
365
- end
1
+ require 'spec_helper'
2
+
3
+ describe Mongoid::History::Options do
4
+ before :each do
5
+ class ModelOne
6
+ include Mongoid::Document
7
+ include Mongoid::History::Trackable
8
+
9
+ store_in collection: :model_ones
10
+
11
+ field :foo
12
+ field :b, as: :bar
13
+
14
+ if Mongoid::Compatibility::Version.mongoid7_or_newer?
15
+ embeds_one :emb_one
16
+ embeds_one :emb_two, store_as: :emtw
17
+ embeds_many :emb_threes
18
+ embeds_many :emb_fours, store_as: :emfs
19
+ else
20
+ embeds_one :emb_one, inverse_class_name: 'EmbOne'
21
+ embeds_one :emb_two, store_as: :emtw, inverse_class_name: 'EmbTwo'
22
+ embeds_many :emb_threes, inverse_class_name: 'EmbThree'
23
+ embeds_many :emb_fours, store_as: :emfs, inverse_class_name: 'EmbFour'
24
+ end
25
+
26
+ track_history
27
+ end
28
+
29
+ class EmbOne
30
+ include Mongoid::Document
31
+
32
+ field :f_em_foo
33
+ field :fmb, as: :f_em_bar
34
+
35
+ embedded_in :model_one
36
+ end
37
+
38
+ class EmbTwo
39
+ include Mongoid::Document
40
+
41
+ field :f_em_baz
42
+ embedded_in :model_one
43
+ end
44
+
45
+ class EmbThree
46
+ include Mongoid::Document
47
+
48
+ field :f_em_foo
49
+ field :fmb, as: :f_em_bar
50
+
51
+ embedded_in :model_one
52
+ end
53
+
54
+ class EmbFour
55
+ include Mongoid::Document
56
+
57
+ field :f_em_baz
58
+ embedded_in :model_one
59
+ end
60
+ end
61
+
62
+ after :each do
63
+ Object.send(:remove_const, :ModelOne)
64
+ Object.send(:remove_const, :EmbOne)
65
+ Object.send(:remove_const, :EmbTwo)
66
+ Object.send(:remove_const, :EmbThree)
67
+ Object.send(:remove_const, :EmbFour)
68
+ end
69
+
70
+ let(:options) { {} }
71
+ let(:service) { described_class.new(ModelOne, options) }
72
+
73
+ subject { service }
74
+
75
+ it { is_expected.to respond_to :trackable }
76
+ it { is_expected.to respond_to :options }
77
+
78
+ describe '#initialize' do
79
+ it { expect(service.trackable).to eq ModelOne }
80
+ end
81
+
82
+ describe '#scope' do
83
+ it { expect(service.scope).to eq :model_one }
84
+ end
85
+
86
+ describe '#parse' do
87
+ it 'does not mutate the original options' do
88
+ original_options = service.options.dup
89
+ service.prepared
90
+ expect(service.options).to eq original_options
91
+ end
92
+
93
+ describe '#default_options' do
94
+ let(:expected_options) do
95
+ {
96
+ on: :all,
97
+ except: %i[created_at updated_at],
98
+ tracker_class_name: nil,
99
+ modifier_field: :modifier,
100
+ version_field: :version,
101
+ changes_method: :changes,
102
+ scope: :model_one,
103
+ track_create: true,
104
+ track_update: true,
105
+ track_destroy: true,
106
+ format: nil
107
+ }
108
+ end
109
+ it { expect(service.send(:default_options)).to eq expected_options }
110
+ end
111
+
112
+ describe '#prepare_skipped_fields' do
113
+ let(:options) { { except: value } }
114
+ subject { service.prepared }
115
+
116
+ context 'with field' do
117
+ let(:value) { :foo }
118
+ it { expect(subject[:except]).to eq %w[foo] }
119
+ end
120
+
121
+ context 'with array of fields' do
122
+ let(:value) { %i[foo] }
123
+ it { expect(subject[:except]).to eq %w[foo] }
124
+ end
125
+
126
+ context 'with field alias' do
127
+ let(:value) { %i[foo bar] }
128
+ it { expect(subject[:except]).to eq %w[foo b] }
129
+ end
130
+
131
+ context 'with duplicate values' do
132
+ let(:value) { %i[foo bar b] }
133
+ it { expect(subject[:except]).to eq %w[foo b] }
134
+ end
135
+
136
+ context 'with blank values' do
137
+ let(:value) { %i[foo] | [nil] }
138
+ it { expect(subject[:except]).to eq %w[foo] }
139
+ end
140
+ end
141
+
142
+ describe '#prepare_formatted_fields' do
143
+ let(:options) { { format: value } }
144
+ subject { service.prepared }
145
+
146
+ context 'with non-hash' do
147
+ let(:value) { :foo }
148
+ it { expect(subject[:format]).to eq({}) }
149
+ end
150
+
151
+ context 'with a field format' do
152
+ let(:value) { { foo: '&&&' } }
153
+ it { expect(subject[:format]).to include 'foo' => '&&&' }
154
+ end
155
+
156
+ context 'with nested format' do
157
+ let(:value) { { emb_one: { f_em_foo: '***' } } }
158
+ it { expect(subject[:format]).to include 'emb_one' => { 'f_em_foo' => '***' } }
159
+ end
160
+ end
161
+
162
+ describe '#parse_tracked_fields_and_relations' do
163
+ context 'when options not passed' do
164
+ let(:expected_options) do
165
+ {
166
+ on: %i[foo b],
167
+ except: %w[created_at updated_at],
168
+ tracker_class_name: nil,
169
+ modifier_field: :modifier,
170
+ version_field: :version,
171
+ changes_method: :changes,
172
+ scope: :model_one,
173
+ track_create: true,
174
+ track_update: true,
175
+ track_destroy: true,
176
+ fields: %w[foo b],
177
+ dynamic: [],
178
+ relations: { embeds_one: {}, embeds_many: {} },
179
+ format: {}
180
+ }
181
+ end
182
+ it { expect(service.prepared).to eq expected_options }
183
+ end
184
+
185
+ context 'when options passed' do
186
+ subject { service.prepared }
187
+
188
+ describe '@options' do
189
+ let(:options) { { on: value } }
190
+
191
+ context 'with field' do
192
+ let(:value) { :foo }
193
+ it { expect(subject[:on]).to eq %i[foo] }
194
+ it { expect(subject[:fields]).to eq %w[foo] }
195
+ end
196
+
197
+ context 'with array of fields' do
198
+ let(:value) { %i[foo] }
199
+ it { expect(subject[:on]).to eq %i[foo] }
200
+ it { expect(subject[:fields]).to eq %w[foo] }
201
+ end
202
+
203
+ context 'with embeds_one relation attributes' do
204
+ let(:value) { { emb_one: %i[f_em_foo] } }
205
+ it { expect(subject[:on]).to eq [[:emb_one, %i[f_em_foo]]] }
206
+ end
207
+
208
+ context 'with fields and embeds_one relation attributes' do
209
+ let(:value) { [:foo, emb_one: %i[f_em_foo]] }
210
+ it { expect(subject[:on]).to eq [:foo, emb_one: %i[f_em_foo]] }
211
+ end
212
+
213
+ context 'with :all' do
214
+ let(:value) { :all }
215
+ it { expect(subject[:on]).to eq %i[foo b] }
216
+ end
217
+
218
+ context 'with :fields' do
219
+ let(:value) { :fields }
220
+ it { expect(subject[:on]).to eq %i[foo b] }
221
+ end
222
+
223
+ describe '#categorize_tracked_option' do
224
+ context 'with skipped field' do
225
+ let(:options) { { on: %i[foo bar], except: :foo } }
226
+ it { expect(subject[:fields]).to eq %w[b] }
227
+ end
228
+
229
+ context 'with skipped embeds_one relation' do
230
+ let(:options) { { on: %i[fields emb_one emb_two], except: :emb_one } }
231
+ it { expect(subject[:relations][:embeds_one]).to eq('emtw' => %w[_id f_em_baz]) }
232
+ end
233
+
234
+ context 'with skipped embeds_many relation' do
235
+ let(:options) { { on: %i[fields emb_threes emb_fours], except: :emb_threes } }
236
+ it { expect(subject[:relations][:embeds_many]).to eq('emfs' => %w[_id f_em_baz]) }
237
+ end
238
+
239
+ context 'with reserved field' do
240
+ let(:options) { { on: %i[_id _type foo deleted_at] } }
241
+ it { expect(subject[:fields]).to eq %w[foo] }
242
+ end
243
+
244
+ context 'when embeds_one attribute passed' do
245
+ let(:options) { { on: { emb_one: :f_em_foo } } }
246
+ it { expect(subject[:relations][:embeds_one]).to eq('emb_one' => %w[_id f_em_foo]) }
247
+ end
248
+
249
+ context 'when embeds_one attributes array passed' do
250
+ let(:options) { { on: { emb_one: %i[f_em_foo] } } }
251
+ it { expect(subject[:relations][:embeds_one]).to eq('emb_one' => %w[_id f_em_foo]) }
252
+ end
253
+
254
+ context 'when embeds_many attribute passed' do
255
+ let(:options) { { on: { emb_threes: :f_em_foo } } }
256
+ it { expect(subject[:relations][:embeds_many]).to eq('emb_threes' => %w[_id f_em_foo]) }
257
+ end
258
+
259
+ context 'when embeds_many attributes array passed' do
260
+ let(:options) { { on: { emb_threes: %i[f_em_foo] } } }
261
+ it { expect(subject[:relations][:embeds_many]).to eq('emb_threes' => %w[_id f_em_foo]) }
262
+ end
263
+
264
+ context 'when embeds_one attributes not passed' do
265
+ let(:options) { { on: :emb_one } }
266
+ it { expect(subject[:relations][:embeds_one]).to eq('emb_one' => %w[_id f_em_foo fmb]) }
267
+ end
268
+
269
+ context 'when embeds_many attributes not passed' do
270
+ let(:options) { { on: :emb_threes } }
271
+ it { expect(subject[:relations][:embeds_many]).to eq('emb_threes' => %w[_id f_em_foo fmb]) }
272
+ end
273
+
274
+ context 'when embeds_one attribute alias passed' do
275
+ let(:options) { { on: { emb_one: %i[f_em_bar] } } }
276
+ it { expect(subject[:relations][:embeds_one]).to eq('emb_one' => %w[_id fmb]) }
277
+ end
278
+
279
+ context 'when embeds_many attribute alias passed' do
280
+ let(:options) { { on: { emb_threes: %i[f_em_bar] } } }
281
+ it { expect(subject[:relations][:embeds_many]).to eq('emb_threes' => %w[_id fmb]) }
282
+ end
283
+
284
+ context 'with fields, and multiple embeds_one, and embeds_many relations' do
285
+ let(:options) { { on: [:foo, :bar, :emb_two, { emb_threes: %i[f_em_foo f_em_bar], emb_fours: :f_em_baz }] } }
286
+ it 'should categorize fields and associations correctly' do
287
+ expect(subject[:fields]).to eq(%w[foo b])
288
+ expect(subject[:relations][:embeds_one]).to eq('emtw' => %w[_id f_em_baz])
289
+ expect(subject[:relations][:embeds_many]).to eq('emb_threes' => %w[_id f_em_foo fmb], 'emfs' => %w[_id f_em_baz])
290
+ end
291
+ end
292
+
293
+ context 'with field alias' do
294
+ let(:options) { { on: :bar } }
295
+ it { expect(subject[:fields]).to eq %w[b] }
296
+ end
297
+
298
+ context 'with dynamic field name' do
299
+ let(:options) { { on: :my_field } }
300
+ it { expect(subject[:dynamic]).to eq %w[my_field] }
301
+ end
302
+
303
+ context 'with relations' do
304
+ let(:options) { { on: :embedded_relations } }
305
+ it do
306
+ expect(subject[:relations]).to eq(
307
+ embeds_many: { 'emb_threes' => %w[_id f_em_foo fmb],
308
+ 'emfs' => %w[_id f_em_baz] },
309
+ embeds_one: { 'emb_one' => %w[_id f_em_foo fmb],
310
+ 'emtw' => %w[_id f_em_baz] }
311
+ )
312
+ end
313
+ end
314
+ end
315
+ end
316
+
317
+ describe ':modifier_field' do
318
+ let(:options) { { modifier_field: :my_modifier_field } }
319
+ it { expect(subject[:modifier_field]).to eq :my_modifier_field }
320
+ end
321
+
322
+ describe ':version_field' do
323
+ let(:options) { { version_field: :my_version_field } }
324
+ it { expect(subject[:version_field]).to eq :my_version_field }
325
+ end
326
+
327
+ describe ':paranoia_field' do
328
+ let(:options) { { paranoia_field: :my_paranoia_field } }
329
+ it { expect(subject[:paranoia_field]).to eq :my_paranoia_field }
330
+ end
331
+
332
+ describe ':changes_method' do
333
+ let(:options) { { changes_method: :my_changes_method } }
334
+ it { expect(subject[:changes_method]).to eq :my_changes_method }
335
+ end
336
+
337
+ describe ':scope' do
338
+ let(:options) { { scope: :my_scope } }
339
+ it { expect(subject[:scope]).to eq :my_scope }
340
+ end
341
+
342
+ describe ':track_create' do
343
+ let(:options) { { track_create: true } }
344
+ it { expect(subject[:track_create]).to be true }
345
+ end
346
+
347
+ describe ':track_update' do
348
+ let(:options) { { track_update: false } }
349
+ it { expect(subject[:track_update]).to be false }
350
+ end
351
+
352
+ describe ':track_destroy' do
353
+ let(:options) { { track_destroy: true } }
354
+ it { expect(subject[:track_destroy]).to be true }
355
+ end
356
+
357
+ describe '#remove_reserved_fields' do
358
+ let(:options) { { on: %i[_id _type foo version modifier_id] } }
359
+ it { expect(subject[:fields]).to eq %w[foo] }
360
+ it { expect(subject[:dynamic]).to eq [] }
361
+ end
362
+ end
363
+ end
364
+ end
365
+ end