hoodoo 2.0.0 → 2.1.1

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.
@@ -1,6 +1,10 @@
1
1
  require 'spec_helper'
2
2
  require 'active_record'
3
3
 
4
+ # Automatic and manual dating tests have their own test files and Finder
5
+ # module features specific to dating are covered there, to keep things more
6
+ # simple here.
7
+ #
4
8
  # The "counting" tests must run first and in-order internally, else e.g. an
5
9
  # ANALYZE might happen before the pre-ANALYZE test, breaking the results.
6
10
  # Other tests that create objects in the table can cause the estimated count
@@ -11,8 +15,7 @@ require 'active_record'
11
15
  describe Hoodoo::ActiveRecord::Finder, :order => :defined do
12
16
  before :all do
13
17
  spec_helper_silence_stdout() do
14
- ActiveRecord::Migration.create_table( :r_spec_model_finder_tests, :id => false ) do | t |
15
- t.text :id
18
+ ActiveRecord::Migration.create_table( :r_spec_model_finder_tests, :id => :string ) do | t |
16
19
  t.text :uuid
17
20
  t.text :code
18
21
  t.text :field_one
@@ -22,6 +25,8 @@ describe Hoodoo::ActiveRecord::Finder, :order => :defined do
22
25
  t.timestamps :null => true
23
26
  t.text :created_by
24
27
  end
28
+
29
+ ActiveRecord::Migration.change_column( :r_spec_model_finder_tests, :id, :string, :limit => 32 )
25
30
  end
26
31
 
27
32
  class RSpecModelFinderTest < ActiveRecord::Base
@@ -65,14 +70,6 @@ describe Hoodoo::ActiveRecord::Finder, :order => :defined do
65
70
  )
66
71
  end
67
72
 
68
- class RSpecModelFinderTestWithDating < ActiveRecord::Base
69
- self.primary_key = :id
70
- self.table_name = :r_spec_model_finder_tests
71
-
72
- include Hoodoo::ActiveRecord::Finder
73
- include Hoodoo::ActiveRecord::Dated
74
- end
75
-
76
73
  class RSpecModelFinderTestWithHelpers < ActiveRecord::Base
77
74
  include Hoodoo::ActiveRecord::Finder
78
75
 
@@ -284,9 +281,9 @@ describe Hoodoo::ActiveRecord::Finder, :order => :defined do
284
281
  # The outer 'before' code ensures an accurate initial count of 3,
285
282
  # but we're going add in a few more unestimated items.
286
283
  #
287
- @uncounted1 = RSpecModelFinderTest.new.save!
288
- @uncounted2 = RSpecModelFinderTest.new.save!
289
- @uncounted3 = RSpecModelFinderTest.new.save!
284
+ @uncounted1 = RSpecModelFinderTest.new( :id => 'unc_id1' ).save!
285
+ @uncounted2 = RSpecModelFinderTest.new( :id => 'unc_id2' ).save!
286
+ @uncounted3 = RSpecModelFinderTest.new( :id => 'unc_id3' ).save!
290
287
 
291
288
  @subsequent_accurate_count = RSpecModelFinderTest.count
292
289
  end
@@ -624,6 +621,42 @@ describe Hoodoo::ActiveRecord::Finder, :order => :defined do
624
621
  found = RSpecModelFinderTest.where( :field_one => @scoped_3.field_one + '!' ).acquire_in( @context )
625
622
  expect( found ).to be_nil
626
623
  end
624
+
625
+ context 'enhanced by #acquire_in!' do
626
+ before :each do
627
+ @session.scoping = { :authorised_uuids => [ 'uuid 1' ], :authorised_code => 'code 1' }
628
+ end
629
+
630
+ # This test proves that the higher level interface uses the lower
631
+ # level interface and, as such, we judge that only the extra added
632
+ # features need test coverage, rather than repeating all of the
633
+ # coverage already done for #acquire_in.
634
+ #
635
+ it 'acquires via #acquire_in' do
636
+ expect( RSpecModelFinderTest ).to receive( :acquire_in ).with( @context ).and_call_original()
637
+
638
+ @context.request.uri_path_components = [ @scoped_1.id ]
639
+ found = RSpecModelFinderTest.acquire_in!( @context )
640
+
641
+ expect( found ).to eq( @scoped_1 )
642
+ end
643
+
644
+ it 'does not add errors when an instance is found' do
645
+ @context.request.uri_path_components = [ @scoped_1.id ]
646
+ RSpecModelFinderTest.acquire_in!( @context )
647
+
648
+ expect( @context.response.halt_processing? ).to eq( false )
649
+ end
650
+
651
+ it 'adds "not_found" if an instance is absent' do
652
+ @context.request.uri_path_components = [ Hoodoo::UUID.generate() ]
653
+ RSpecModelFinderTest.acquire_in!( @context )
654
+
655
+ expect( @context.response.halt_processing? ).to eq( true )
656
+ expect( @context.response.errors.errors.count ).to eq( 1 )
657
+ expect( @context.response.errors.errors[ 0 ][ 'code' ] ).to eq( 'generic.not_found' )
658
+ end
659
+ end
627
660
  end
628
661
 
629
662
  # ========================================================================
@@ -11,9 +11,8 @@ describe Hoodoo::ActiveRecord::ManuallyDated do
11
11
 
12
12
  before :all do
13
13
  spec_helper_silence_stdout() do
14
- ActiveRecord::Migration.create_table( :r_spec_model_manual_date_tests, :id => false ) do | t |
14
+ ActiveRecord::Migration.create_table( :r_spec_model_manual_date_tests, :id => :string ) do | t |
15
15
  t.string :uuid, :null => false, :length => 32
16
- t.string :id, :null => false, :length => 32
17
16
 
18
17
  t.text :data
19
18
  t.text :unique
@@ -23,6 +22,8 @@ describe Hoodoo::ActiveRecord::ManuallyDated do
23
22
  t.datetime :effective_end, :null => false
24
23
  end
25
24
 
25
+ ActiveRecord::Migration.change_column( :r_spec_model_manual_date_tests, :id, :string, :limit => 32 )
26
+
26
27
  # Documentation recommends these constraints in migrations, so ensure
27
28
  # everything works when they're present.
28
29
 
@@ -49,6 +50,7 @@ describe Hoodoo::ActiveRecord::ManuallyDated do
49
50
 
50
51
  class RSpecModelManualDateTest < ActiveRecord::Base
51
52
  include Hoodoo::ActiveRecord::ManuallyDated
53
+
52
54
  manual_dating_enabled()
53
55
 
54
56
  validates_each :data do | record, attribute, value |
@@ -57,6 +59,13 @@ describe Hoodoo::ActiveRecord::ManuallyDated do
57
59
  end
58
60
  end
59
61
  end
62
+
63
+ class RSpecModelManualDateTestOverride < ActiveRecord::Base
64
+ include Hoodoo::ActiveRecord::ManuallyDated
65
+
66
+ self.table_name = :r_spec_model_manual_date_tests
67
+ manual_dating_enabled()
68
+ end
60
69
  end
61
70
 
62
71
  # Create some example data for finding. The data has two different UUIDs
@@ -279,6 +288,158 @@ describe Hoodoo::ActiveRecord::ManuallyDated do
279
288
  end
280
289
  end
281
290
 
291
+ # ==========================================================================
292
+ # Hoodoo::ActiveRecord::Finder interaction
293
+ # ==========================================================================
294
+
295
+ context 'with Hoodoo::ActiveRecord::Finder support' do
296
+ before :each do
297
+ interaction = Hoodoo::Services::Middleware::Interaction.new( {}, nil )
298
+ interaction.context = Hoodoo::Services::Context.new(
299
+ Hoodoo::Services::Session.new,
300
+ interaction.context.request,
301
+ interaction.context.response,
302
+ interaction
303
+ )
304
+
305
+ @context = interaction.context
306
+ end
307
+
308
+ context '#scoped_in' do
309
+ it 'generates appropriate scope' do
310
+ expect( Hoodoo::ActiveRecord::Support ).to(
311
+ receive( :full_scope_for ).once().with(
312
+ RSpecModelManualDateTestOverride, @context
313
+ ).and_call_original()
314
+ )
315
+
316
+ sql = RSpecModelManualDateTestOverride.scoped_in( @context ).to_sql
317
+
318
+ expect( sql ).to_not include( "UNION ALL" ) # This is only present in auto-dating, not manual dating
319
+ expect( sql ).to include( " AND \"r_spec_model_manual_date_tests\".\"effective_end\" > '" )
320
+ end
321
+
322
+ it 'generates appropriate undated scope' do
323
+ expect( Hoodoo::ActiveRecord::Support ).to(
324
+ receive( :add_undated_scope_to ).once().with(
325
+ kind_of( ActiveRecord::Relation ), RSpecModelManualDateTestOverride, @context
326
+ ).and_call_original()
327
+ )
328
+
329
+ sql = RSpecModelManualDateTestOverride.scoped_undated_in( @context ).to_sql
330
+
331
+ expect( sql ).to eq( "SELECT \"r_spec_model_manual_date_tests\".* FROM \"r_spec_model_manual_date_tests\"" )
332
+ end
333
+ end
334
+
335
+ context '#acquire_in' do
336
+ context 'with contemporary' do
337
+ it 'finds the contemporary record' do
338
+ @context.request.dated_at = nil
339
+ @context.request.uri_path_components = [ @uuid_a ]
340
+
341
+ result = RSpecModelManualDateTestOverride.acquire_in!( @context )
342
+
343
+ expect( @context.response.halt_processing? ).to eq( false )
344
+ expect( result.data ).to eq( 'six' )
345
+ end
346
+
347
+ it 'finds a historic record' do
348
+ @context.request.dated_at = @now - 4.hours
349
+ @context.request.uri_path_components = [ @uuid_a ]
350
+
351
+ result = RSpecModelManualDateTestOverride.acquire_in!( @context )
352
+
353
+ expect( @context.response.halt_processing? ).to eq( false )
354
+ expect( result.data ).to eq( 'one' )
355
+ end
356
+
357
+ it 'indicates correctly that a contemporary exists during a far-backdated lookup' do
358
+ @context.request.dated_at = @now - 1.year
359
+ @context.request.uri_path_components = [ @uuid_a ]
360
+
361
+ result = RSpecModelManualDateTestOverride.acquire_in!( @context )
362
+
363
+ expect( @context.response.halt_processing? ).to eq( true )
364
+ expect( @context.response.errors.errors.count ).to eq( 2 )
365
+
366
+ expect( @context.response.errors.errors[ 0 ][ 'code' ] ).to eq( 'generic.not_found' )
367
+ expect( @context.response.errors.errors[ 1 ][ 'code' ] ).to eq( 'generic.contemporary_exists' )
368
+ expect( @context.response.errors.errors[ 0 ][ 'reference' ] ).to eq( @uuid_a )
369
+ expect( @context.response.errors.errors[ 1 ][ 'reference' ] ).to eq( @uuid_a )
370
+ end
371
+ end
372
+
373
+ context 'with a UUID that matches no existing record' do
374
+ it 'indicates correctly that no record exists and does not say a contemporary is present' do
375
+ alt_uuid = Hoodoo::UUID.generate
376
+ @context.request.dated_at = @now - 5.seconds
377
+ @context.request.uri_path_components = [ alt_uuid ]
378
+
379
+ result = RSpecModelManualDateTestOverride.acquire_in!( @context )
380
+
381
+ expect( @context.response.halt_processing? ).to eq( true )
382
+ expect( @context.response.errors.errors.count ).to eq( 1 )
383
+
384
+ expect( @context.response.errors.errors[ 0 ][ 'code' ] ).to eq( 'generic.not_found' )
385
+ expect( @context.response.errors.errors[ 0 ][ 'reference' ] ).to eq( alt_uuid )
386
+ end
387
+ end
388
+
389
+ context 'without contemporary' do
390
+ before( :each ) do
391
+ @context.request.dated_at = nil
392
+
393
+ RSpecModelManualDateTest.manually_dated_destruction_in(
394
+ @context,
395
+ ident: @uuid_a
396
+ )
397
+
398
+ sleep( ( 0.1 ** Hoodoo::ActiveRecord::ManuallyDated::SECONDS_DECIMAL_PLACES ) * 2 )
399
+ end
400
+
401
+ it 'finds no contemporary record' do
402
+ @context.request.dated_at = nil
403
+ @context.request.uri_path_components = [ @uuid_a ]
404
+
405
+ result = RSpecModelManualDateTest.acquire_in!( @context )
406
+ expect( result ).to be_nil
407
+
408
+ expect( @context.response.halt_processing? ).to eq( true )
409
+ expect( @context.response.errors.errors.count ).to eq( 1 )
410
+
411
+ expect( @context.response.errors.errors[ 0 ][ 'code' ] ).to eq( 'generic.not_found' )
412
+ expect( @context.response.errors.errors[ 0 ][ 'reference' ] ).to eq( @uuid_a )
413
+ end
414
+
415
+ it 'finds a historic record' do
416
+ @context.request.dated_at = @now - 4.hours
417
+ @context.request.uri_path_components = [ @uuid_a ]
418
+
419
+ result = RSpecModelManualDateTest.acquire_in!( @context )
420
+ expect( result ).to_not be_nil
421
+
422
+ expect( @context.response.halt_processing? ).to eq( false )
423
+ expect( result.data ).to eq( 'one' )
424
+ end
425
+
426
+ it 'indicates correctly that no contemporary exists during a far-backdated lookup' do
427
+ @context.request.dated_at = @now - 1.year
428
+ @context.request.uri_path_components = [ @uuid_a ]
429
+
430
+ result = RSpecModelManualDateTest.acquire_in!( @context )
431
+ expect( result ).to be_nil
432
+
433
+ expect( @context.response.halt_processing? ).to eq( true )
434
+ expect( @context.response.errors.errors.count ).to eq( 1 )
435
+
436
+ expect( @context.response.errors.errors[ 0 ][ 'code' ] ).to eq( 'generic.not_found' )
437
+ expect( @context.response.errors.errors[ 0 ][ 'reference' ] ).to eq( @uuid_a )
438
+ end
439
+ end
440
+ end
441
+ end
442
+
282
443
  # ==========================================================================
283
444
  # Writing tests
284
445
  # ==========================================================================
@@ -59,7 +59,7 @@ describe Hoodoo::ActiveRecord::Support do
59
59
  end
60
60
  end
61
61
 
62
- context '#full_scope_for' do
62
+ context '#full_scope_for and #add_undated_scope_to' do
63
63
 
64
64
  # Here we not only test the full scope generator with all mixins included,
65
65
  # and test them all in a *deactivated* state, we also check that inheritance
@@ -214,9 +214,9 @@ describe Hoodoo::ActiveRecord::Support do
214
214
 
215
215
  pending 'translated' # Scope verification for '#translated'
216
216
 
217
- # In this last one, we actually check full_scope_for; activations are in
218
- # the subclass so we drive the non-context versions directly to verify
219
- # that the context chain worked.
217
+ # Finally, we actually check full_scope_for / add_undated_scope_to;
218
+ # activations are in the subclass so we drive the non-context versions
219
+ # directly to verify that the context chain worked.
220
220
 
221
221
  it 'everything' do
222
222
  auto_scope = described_class.full_scope_for( RSpecFullScopeForTestSubclass, @context ).to_sql()
@@ -224,6 +224,18 @@ describe Hoodoo::ActiveRecord::Support do
224
224
 
225
225
  expect( auto_scope ).to eq( manual_scope )
226
226
  end
227
+
228
+ it 'undated' do
229
+ auto_scope = described_class.add_undated_scope_to(
230
+ RSpecFullScopeForTestSubclass.all(),
231
+ RSpecFullScopeForTestSubclass,
232
+ @context
233
+ ).to_sql()
234
+
235
+ manual_scope = RSpecFullScopeForTestSubclass.secure( @context ).translated( @context ).to_sql()
236
+
237
+ expect( auto_scope ).to eq( manual_scope )
238
+ end
227
239
  end
228
240
  end
229
241
 
@@ -285,6 +297,18 @@ describe Hoodoo::ActiveRecord::Support do
285
297
 
286
298
  expect( auto_scope ).to eq( manual_scope )
287
299
  end
300
+
301
+ it 'undated' do
302
+ auto_scope = described_class.add_undated_scope_to(
303
+ RSpecFullScopeForManuallyDated.all(),
304
+ RSpecFullScopeForManuallyDated,
305
+ @context
306
+ ).to_sql()
307
+
308
+ manual_scope = RSpecFullScopeForManuallyDated.secure( @context ).translated( @context ).to_sql()
309
+
310
+ expect( auto_scope ).to eq( manual_scope )
311
+ end
288
312
  end
289
313
  end
290
314
  end
@@ -6,11 +6,10 @@ describe Hoodoo::ActiveRecord::UUID do
6
6
  spec_helper_silence_stdout() do
7
7
  tblname = :r_spec_model_uuid_tests
8
8
 
9
- ActiveRecord::Migration.create_table( tblname, :id => false ) do | t |
10
- t.string( :id, :limit => 32, :null => false )
9
+ ActiveRecord::Migration.create_table( tblname, :id => :string ) do | t |
11
10
  end
12
11
 
13
- ActiveRecord::Migration.add_index( tblname, :id, :unique => true )
12
+ ActiveRecord::Migration.change_column( tblname, :id, :string, :limit => 32 )
14
13
 
15
14
  class RSpecModelUUIDTest < ActiveRecord::Base
16
15
  include Hoodoo::ActiveRecord::UUID
@@ -29,8 +29,7 @@ describe Hoodoo::ActiveRecord::Writer do
29
29
 
30
30
  before( :all ) do
31
31
  spec_helper_silence_stdout() do
32
- ActiveRecord::Migration.create_table(:r_spec_model_writer_tests, :id => false) do | t |
33
- t.text :id
32
+ ActiveRecord::Migration.create_table(:r_spec_model_writer_tests, :id => :string) do | t |
34
33
  t.text :uuid
35
34
  t.text :code
36
35
  t.text :random_field
@@ -38,6 +37,7 @@ describe Hoodoo::ActiveRecord::Writer do
38
37
  t.timestamps :null => false
39
38
  end
40
39
 
40
+ ActiveRecord::Migration.change_column( :r_spec_model_writer_tests, :id, :string, :limit => 32 )
41
41
  ActiveRecord::Migration.add_index(:r_spec_model_writer_tests, :code, unique: true)
42
42
  end
43
43
  end
@@ -274,14 +274,30 @@ describe Hoodoo::Services::Response do
274
274
  end
275
275
 
276
276
  context '#not_found' do
277
-
278
277
  let(:ident) { 'an_ident' }
279
278
  before { @r.not_found(ident) }
280
279
 
281
280
  it 'sets the generic.not_found code' do
281
+ expect(@r.errors.errors.count).to eq(1)
282
282
  expect(@r.errors.errors.first['code']).to eq('generic.not_found')
283
283
  end
284
- it 'sets the the reference to be the ident passed in' do
284
+ it 'sets the reference to be the ident passed in' do
285
+ expect(@r.errors.errors.first['reference']).to eq(ident)
286
+ end
287
+ it 'sets halt processing to true' do
288
+ expect(@r.halt_processing?).to eq(true)
289
+ end
290
+ end
291
+
292
+ context '#contemporary_exists' do
293
+ let(:ident) { 'an_ident' }
294
+ before { @r.contemporary_exists(ident) }
295
+
296
+ it 'sets the generic.contemporary_exists code' do
297
+ expect(@r.errors.errors.count).to eq(1)
298
+ expect(@r.errors.errors.first['code']).to eq('generic.contemporary_exists')
299
+ end
300
+ it 'sets the reference to be the ident passed in' do
285
301
  expect(@r.errors.errors.first['reference']).to eq(ident)
286
302
  end
287
303
  it 'sets halt processing to true' do
data/spec/spec_helper.rb CHANGED
@@ -167,7 +167,10 @@ end
167
167
  [ Hoodoo::Monkey::Patch, Hoodoo::Monkey::Chaos ].each do | monkey |
168
168
  monkey.constants.each do | extension_module_name |
169
169
  extension_module = monkey.const_get( extension_module_name )
170
- Hoodoo::Monkey.disable( extension_module: extension_module )
170
+
171
+ # Ignore "not registered" exceptions for not-yet-registered patches.
172
+ #
173
+ Hoodoo::Monkey.disable( extension_module: extension_module ) rescue nil
171
174
  end
172
175
  end
173
176
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hoodoo
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Loyalty New Zealand
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-13 00:00:00.000000000 Z
11
+ date: 2017-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: dalli
@@ -72,14 +72,14 @@ dependencies:
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '4.3'
75
+ version: '5.1'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '4.3'
82
+ version: '5.1'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rack-test
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -317,6 +317,8 @@ files:
317
317
  - lib/hoodoo/middleware.rb
318
318
  - lib/hoodoo/monkey.rb
319
319
  - lib/hoodoo/monkey/monkey.rb
320
+ - lib/hoodoo/monkey/patch/active_record_dated_finder_additions.rb
321
+ - lib/hoodoo/monkey/patch/active_record_manually_dated_finder_additions.rb
320
322
  - lib/hoodoo/monkey/patch/datadog_traced_amqp.rb
321
323
  - lib/hoodoo/monkey/patch/newrelic_middleware_analytics.rb
322
324
  - lib/hoodoo/monkey/patch/newrelic_traced_amqp.rb
@@ -524,7 +526,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
524
526
  version: '0'
525
527
  requirements: []
526
528
  rubyforge_project:
527
- rubygems_version: 2.6.14
529
+ rubygems_version: 2.7.0
528
530
  signing_key:
529
531
  specification_version: 4
530
532
  summary: Opinionated APIs