mongoid-history 0.8.3 → 0.8.5
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.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -1
- data/.document +5 -5
- data/.github/workflows/test.yml +72 -0
- data/.gitignore +46 -46
- data/.rspec +2 -2
- data/.rubocop.yml +6 -6
- data/.rubocop_todo.yml +99 -99
- data/CHANGELOG.md +173 -163
- data/CONTRIBUTING.md +117 -118
- data/Dangerfile +1 -1
- data/Gemfile +49 -40
- data/LICENSE.txt +20 -20
- data/README.md +609 -608
- data/RELEASING.md +66 -67
- data/Rakefile +24 -24
- data/UPGRADING.md +53 -53
- data/lib/mongoid/history/attributes/base.rb +72 -72
- data/lib/mongoid/history/attributes/create.rb +45 -45
- data/lib/mongoid/history/attributes/destroy.rb +34 -34
- data/lib/mongoid/history/attributes/update.rb +104 -104
- data/lib/mongoid/history/options.rb +177 -177
- data/lib/mongoid/history/trackable.rb +588 -583
- data/lib/mongoid/history/tracker.rb +247 -247
- data/lib/mongoid/history/version.rb +5 -5
- data/lib/mongoid/history.rb +77 -77
- data/lib/mongoid-history.rb +1 -1
- data/mongoid-history.gemspec +25 -25
- data/perf/benchmark_modified_attributes_for_create.rb +65 -65
- data/perf/gc_suite.rb +21 -21
- data/spec/integration/embedded_in_polymorphic_spec.rb +112 -112
- data/spec/integration/integration_spec.rb +976 -976
- data/spec/integration/multi_relation_spec.rb +47 -47
- data/spec/integration/multiple_trackers_spec.rb +68 -68
- data/spec/integration/nested_embedded_documents_spec.rb +64 -64
- data/spec/integration/nested_embedded_documents_tracked_in_parent_spec.rb +124 -124
- data/spec/integration/nested_embedded_polymorphic_documents_spec.rb +115 -115
- data/spec/integration/subclasses_spec.rb +47 -47
- data/spec/integration/track_history_order_spec.rb +84 -84
- data/spec/integration/validation_failure_spec.rb +76 -76
- data/spec/spec_helper.rb +32 -30
- data/spec/support/error_helpers.rb +7 -0
- data/spec/support/mongoid.rb +11 -11
- data/spec/support/mongoid_history.rb +12 -12
- data/spec/unit/attributes/base_spec.rb +141 -141
- data/spec/unit/attributes/create_spec.rb +342 -342
- data/spec/unit/attributes/destroy_spec.rb +228 -228
- data/spec/unit/attributes/update_spec.rb +342 -342
- data/spec/unit/callback_options_spec.rb +165 -165
- data/spec/unit/embedded_methods_spec.rb +87 -87
- data/spec/unit/history_spec.rb +58 -58
- data/spec/unit/my_instance_methods_spec.rb +555 -555
- data/spec/unit/options_spec.rb +365 -365
- data/spec/unit/singleton_methods_spec.rb +406 -406
- data/spec/unit/store/default_store_spec.rb +11 -11
- data/spec/unit/store/request_store_spec.rb +13 -13
- data/spec/unit/trackable_spec.rb +1057 -987
- data/spec/unit/tracker_spec.rb +190 -190
- metadata +9 -7
- data/.travis.yml +0 -36
data/spec/unit/options_spec.rb
CHANGED
@@ -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
|