shoulda-matchers 4.1.2 → 4.5.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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/{MIT-LICENSE → LICENSE} +1 -1
  3. data/README.md +168 -86
  4. data/lib/shoulda/matchers/action_controller/callback_matcher.rb +4 -2
  5. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +3 -2
  6. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +26 -21
  7. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +6 -8
  8. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +6 -8
  9. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +16 -13
  10. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +2 -1
  11. data/lib/shoulda/matchers/action_controller/route_matcher.rb +5 -6
  12. data/lib/shoulda/matchers/action_controller/route_params.rb +1 -1
  13. data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +19 -13
  14. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +18 -16
  15. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +31 -29
  16. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +1 -1
  17. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +5 -5
  18. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +2 -2
  19. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +1 -1
  20. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +1 -1
  21. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +1 -1
  22. data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +51 -25
  23. data/lib/shoulda/matchers/active_model/helpers.rb +1 -1
  24. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +32 -30
  25. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +1 -1
  26. data/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +1 -1
  27. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +9 -1
  28. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +2 -2
  29. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +9 -8
  30. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +28 -46
  31. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +33 -9
  32. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +71 -26
  33. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +2 -2
  34. data/lib/shoulda/matchers/active_model/validation_matcher.rb +31 -6
  35. data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +2 -4
  36. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +2 -4
  37. data/lib/shoulda/matchers/active_model/validator.rb +3 -3
  38. data/lib/shoulda/matchers/active_record.rb +26 -23
  39. data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +6 -3
  40. data/lib/shoulda/matchers/active_record/association_matcher.rb +100 -44
  41. data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +5 -2
  42. data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +4 -4
  43. data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +1 -1
  44. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +11 -6
  45. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +14 -15
  46. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +30 -8
  47. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +23 -5
  48. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +3 -3
  49. data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +1 -1
  50. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +3 -3
  51. data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +3 -2
  52. data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +7 -5
  53. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +8 -8
  54. data/lib/shoulda/matchers/active_record/have_attached_matcher.rb +185 -0
  55. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +40 -18
  56. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +1 -1
  57. data/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +106 -0
  58. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +12 -10
  59. data/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +83 -0
  60. data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +30 -9
  61. data/lib/shoulda/matchers/active_record/serialize_matcher.rb +13 -9
  62. data/lib/shoulda/matchers/active_record/uniqueness.rb +1 -1
  63. data/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +1 -3
  64. data/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +0 -2
  65. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +80 -73
  66. data/lib/shoulda/matchers/doublespeak.rb +2 -1
  67. data/lib/shoulda/matchers/doublespeak/double.rb +1 -1
  68. data/lib/shoulda/matchers/doublespeak/double_collection.rb +3 -3
  69. data/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +8 -5
  70. data/lib/shoulda/matchers/doublespeak/object_double.rb +1 -1
  71. data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +1 -5
  72. data/lib/shoulda/matchers/doublespeak/world.rb +2 -2
  73. data/lib/shoulda/matchers/error.rb +1 -1
  74. data/lib/shoulda/matchers/independent.rb +0 -1
  75. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +14 -13
  76. data/lib/shoulda/matchers/integrations/configuration.rb +1 -1
  77. data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +1 -1
  78. data/lib/shoulda/matchers/integrations/libraries/rails.rb +2 -2
  79. data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +1 -1
  80. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +1 -1
  81. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +1 -1
  82. data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +1 -1
  83. data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +1 -1
  84. data/lib/shoulda/matchers/rails_shim.rb +10 -21
  85. data/lib/shoulda/matchers/util.rb +16 -4
  86. data/lib/shoulda/matchers/util/word_wrap.rb +8 -8
  87. data/lib/shoulda/matchers/version.rb +1 -1
  88. data/lib/shoulda/matchers/warn.rb +3 -3
  89. data/shoulda-matchers.gemspec +10 -7
  90. metadata +11 -9
  91. data/lib/shoulda/matchers/independent/delegate_method_matcher/stubbed_target.rb +0 -37
@@ -1,6 +1,6 @@
1
1
  module Shoulda
2
2
  module Matchers
3
- module ActiveModel
3
+ module ActiveRecord
4
4
  # @private
5
5
  module Uniqueness
6
6
  end
@@ -1,5 +1,3 @@
1
- require 'thread'
2
-
3
1
  module Shoulda
4
2
  module Matchers
5
3
  module ActiveRecord
@@ -37,7 +35,7 @@ module Shoulda
37
35
  def new_model
38
36
  @_new_model ||= Model.next_unique_copy_of(
39
37
  model_name_without_namespace,
40
- namespace
38
+ namespace,
41
39
  )
42
40
  end
43
41
 
@@ -1,5 +1,3 @@
1
- require 'thread'
2
-
3
1
  module Shoulda
4
2
  module Matchers
5
3
  module ActiveRecord
@@ -80,7 +80,7 @@ module Shoulda
80
80
  #
81
81
  # RSpec.describe Post, type: :model do
82
82
  # describe "validations" do
83
- # subject { Post.create(content: "Here is the content") }
83
+ # subject { Post.new(content: "Here is the content") }
84
84
  # it { should validate_uniqueness_of(:title) }
85
85
  # end
86
86
  # end
@@ -92,7 +92,7 @@ module Shoulda
92
92
  #
93
93
  # RSpec.describe Post, type: :model do
94
94
  # describe "validations" do
95
- # subject { FactoryBot.create(:post) }
95
+ # subject { FactoryBot.build(:post) }
96
96
  # it { should validate_uniqueness_of(:title) }
97
97
  # end
98
98
  # end
@@ -157,6 +157,12 @@ module Shoulda
157
157
  # should validate_uniqueness_of(:slug).scoped_to(:journal_id)
158
158
  # end
159
159
  #
160
+ # NOTE: Support for testing uniqueness validation scoped to an array of
161
+ # associations is not available.
162
+ #
163
+ # For more information, please refer to
164
+ # https://github.com/thoughtbot/shoulda-matchers/issues/814
165
+ #
160
166
  # ##### case_insensitive
161
167
  #
162
168
  # Use `case_insensitive` to test usage of the `:case_sensitive` option
@@ -264,14 +270,14 @@ module Shoulda
264
270
  super(attribute)
265
271
  @expected_message = :taken
266
272
  @options = {
267
- case_sensitivity_strategy: :sensitive
273
+ case_sensitivity_strategy: :sensitive,
268
274
  }
269
275
  @existing_record_created = false
270
276
  @failure_reason = nil
271
277
  @failure_reason_when_negated = nil
272
278
  @attribute_setters = {
273
279
  existing_record: AttributeSetters.new,
274
- new_record: AttributeSetters.new
280
+ new_record: AttributeSetters.new,
275
281
  }
276
282
  end
277
283
 
@@ -396,7 +402,7 @@ module Shoulda
396
402
  end
397
403
 
398
404
  def validations
399
- model._validators[@attribute].select do |validator|
405
+ model.validators_on(@attribute).select do |validator|
400
406
  validator.is_a?(::ActiveRecord::Validations::UniquenessValidator)
401
407
  end
402
408
  end
@@ -407,11 +413,12 @@ module Shoulda
407
413
  else
408
414
  @failure_reason = 'Expected the validation '
409
415
 
410
- if expected_scopes.empty?
411
- @failure_reason << 'not to be scoped to anything, '
412
- else
413
- @failure_reason << "to be scoped to #{inspected_expected_scopes}, "
414
- end
416
+ @failure_reason <<
417
+ if expected_scopes.empty?
418
+ 'not to be scoped to anything, '
419
+ else
420
+ "to be scoped to #{inspected_expected_scopes}, "
421
+ end
415
422
 
416
423
  if actual_sets_of_scopes.any?
417
424
  @failure_reason << 'but it was scoped to '
@@ -455,7 +462,7 @@ module Shoulda
455
462
  def inspected_actual_scopes
456
463
  inspected_actual_sets_of_scopes.to_sentence(
457
464
  words_connector: ' and ',
458
- last_word_connector: ', and'
465
+ last_word_connector: ', and',
459
466
  )
460
467
  end
461
468
 
@@ -491,7 +498,9 @@ module Shoulda
491
498
  def does_not_match_allow_nil?
492
499
  expects_to_allow_nil? && (
493
500
  update_existing_record!(nil) &&
494
- (@failure_reason = nil || disallows_value_of(nil, @expected_message))
501
+ (@failure_reason = nil ||
502
+ disallows_value_of(nil, @expected_message)
503
+ )
495
504
  )
496
505
  end
497
506
 
@@ -527,21 +536,15 @@ module Shoulda
527
536
  end
528
537
 
529
538
  def find_existing_record
530
- record = model.first
531
-
532
- if record.present?
533
- record
534
- else
535
- nil
536
- end
539
+ model.first.presence
537
540
  end
538
541
 
539
542
  def create_existing_record
540
543
  @given_record.tap do |existing_record|
541
544
  existing_record.save(validate: false)
542
545
  end
543
- rescue ::ActiveRecord::StatementInvalid => error
544
- raise ExistingRecordInvalid.create(underlying_exception: error)
546
+ rescue ::ActiveRecord::StatementInvalid => e
547
+ raise ExistingRecordInvalid.create(underlying_exception: e)
545
548
  end
546
549
 
547
550
  def update_existing_record!(value)
@@ -577,7 +580,7 @@ module Shoulda
577
580
  attribute_names_under_test.each do |attribute_name|
578
581
  set_attribute_on_new_record!(
579
582
  attribute_name,
580
- existing_record.public_send(attribute_name)
583
+ existing_record.public_send(attribute_name),
581
584
  )
582
585
  end
583
586
 
@@ -619,11 +622,12 @@ module Shoulda
619
622
 
620
623
  reason << inspected_scopes.to_sentence
621
624
 
622
- if inspected_scopes.many?
623
- reason << " do not seem to be attributes"
624
- else
625
- reason << " does not seem to be an attribute"
626
- end
625
+ reason <<
626
+ if inspected_scopes.many?
627
+ ' do not seem to be attributes'
628
+ else
629
+ ' does not seem to be an attribute'
630
+ end
627
631
 
628
632
  reason << " on #{model.name}."
629
633
 
@@ -643,11 +647,12 @@ module Shoulda
643
647
 
644
648
  reason << inspected_scopes.to_sentence
645
649
 
646
- if inspected_scopes.many?
647
- reason << " seem to be attributes"
648
- else
649
- reason << " seems to be an attribute"
650
- end
650
+ reason <<
651
+ if inspected_scopes.many?
652
+ ' seem to be attributes'
653
+ else
654
+ ' seems to be an attribute'
655
+ end
651
656
 
652
657
  reason << " on #{model.name}."
653
658
 
@@ -658,14 +663,14 @@ module Shoulda
658
663
  end
659
664
 
660
665
  def scopes_present_on_model
661
- @_present_scopes ||= expected_scopes.select do |scope|
666
+ @_scopes_present_on_model ||= expected_scopes.select do |scope|
662
667
  model.method_defined?("#{scope}=")
663
668
  end
664
669
  end
665
670
 
666
671
  def scopes_missing_on_model
667
- @_missing_scopes ||= expected_scopes.select do |scope|
668
- !model.method_defined?("#{scope}=")
672
+ @_scopes_missing_on_model ||= expected_scopes.reject do |scope|
673
+ model.method_defined?("#{scope}=")
669
674
  end
670
675
  end
671
676
 
@@ -697,7 +702,7 @@ module Shoulda
697
702
  raise NonCaseSwappableValueError.create(
698
703
  model: model,
699
704
  attribute: @attribute,
700
- value: value
705
+ value: value,
701
706
  )
702
707
  end
703
708
 
@@ -724,7 +729,7 @@ module Shoulda
724
729
  raise NonCaseSwappableValueError.create(
725
730
  model: model,
726
731
  attribute: @attribute,
727
- value: value
732
+ value: value,
728
733
  )
729
734
  end
730
735
 
@@ -789,7 +794,7 @@ module Shoulda
789
794
  column = column_for(scope)
790
795
 
791
796
  if column.respond_to?(:array) && column.array
792
- [ dummy_scalar_value_for(column) ]
797
+ [dummy_scalar_value_for(column)]
793
798
  else
794
799
  dummy_scalar_value_for(column)
795
800
  end
@@ -801,7 +806,7 @@ module Shoulda
801
806
 
802
807
  def next_value_for(scope, previous_value)
803
808
  if previous_value.is_a?(Array)
804
- [ next_scalar_value_for(scope, previous_value[0]) ]
809
+ [next_scalar_value_for(scope, previous_value[0])]
805
810
  else
806
811
  next_scalar_value_for(scope, previous_value)
807
812
  end
@@ -820,7 +825,7 @@ module Shoulda
820
825
  elsif previous_value.respond_to?(:next)
821
826
  previous_value.next
822
827
  elsif previous_value.respond_to?(:to_datetime)
823
- previous_value.to_datetime.next
828
+ previous_value.to_datetime.in(60).next
824
829
  elsif boolean_value?(previous_value)
825
830
  !previous_value
826
831
  else
@@ -857,7 +862,7 @@ module Shoulda
857
862
  attribute_setter = build_attribute_setter(
858
863
  record,
859
864
  attribute_name,
860
- value
865
+ value,
861
866
  )
862
867
  attribute_setter.set!
863
868
 
@@ -869,7 +874,7 @@ module Shoulda
869
874
  :existing_record,
870
875
  existing_record,
871
876
  attribute_name,
872
- value
877
+ value,
873
878
  )
874
879
  end
875
880
 
@@ -878,7 +883,7 @@ module Shoulda
878
883
  :new_record,
879
884
  new_record,
880
885
  attribute_name,
881
- value
886
+ value,
882
887
  )
883
888
  end
884
889
 
@@ -896,13 +901,14 @@ module Shoulda
896
901
  end
897
902
 
898
903
  def build_attribute_setter(record, attribute_name, value)
899
- Shoulda::Matchers::ActiveModel::AllowValueMatcher::AttributeSetter.new(
900
- matcher_name: :validate_uniqueness_of,
901
- object: record,
902
- attribute_name: attribute_name,
903
- value: value,
904
- ignore_interference_by_writer: ignore_interference_by_writer
905
- )
904
+ Shoulda::Matchers::ActiveModel::AllowValueMatcher::AttributeSetter.
905
+ new(
906
+ matcher_name: :validate_uniqueness_of,
907
+ object: record,
908
+ attribute_name: attribute_name,
909
+ value: value,
910
+ ignore_interference_by_writer: ignore_interference_by_writer,
911
+ )
906
912
  end
907
913
 
908
914
  def existing_value_read
@@ -929,7 +935,7 @@ module Shoulda
929
935
  @given_record.class
930
936
  end
931
937
 
932
- def failure_message_preface
938
+ def failure_message_preface # rubocop:disable Metrics/MethodLength
933
939
  prefix = ''
934
940
 
935
941
  if @existing_record_created
@@ -938,30 +944,28 @@ module Shoulda
938
944
  if attribute_setter_for_existing_record
939
945
  prefix << ', setting '
940
946
  prefix << description_for_attribute_setter(
941
- attribute_setter_for_existing_record
947
+ attribute_setter_for_existing_record,
942
948
  )
943
949
  else
944
950
  prefix << ", whose :#{attribute} is "
945
951
  prefix << "‹#{existing_value_read.inspect}›"
946
952
  end
947
953
 
948
- prefix << ", and saving it as the existing record, then"
954
+ prefix << ', and saving it as the existing record, then'
955
+ elsif attribute_setter_for_existing_record
956
+ prefix << "Given an existing #{model.name},"
957
+ prefix << ' after setting '
958
+ prefix << description_for_attribute_setter(
959
+ attribute_setter_for_existing_record,
960
+ )
961
+ prefix << ', then'
949
962
  else
950
- if attribute_setter_for_existing_record
951
- prefix << "Given an existing #{model.name},"
952
- prefix << ' after setting '
953
- prefix << description_for_attribute_setter(
954
- attribute_setter_for_existing_record
955
- )
956
- prefix << ', then'
957
- else
958
- prefix << "Given an existing #{model.name} whose :#{attribute}"
959
- prefix << ' is '
960
- prefix << Shoulda::Matchers::Util.inspect_value(
961
- existing_value_read
962
- )
963
- prefix << ', after'
964
- end
963
+ prefix << "Given an existing #{model.name} whose :#{attribute}"
964
+ prefix << ' is '
965
+ prefix << Shoulda::Matchers::Util.inspect_value(
966
+ existing_value_read,
967
+ )
968
+ prefix << ', after'
965
969
  end
966
970
 
967
971
  prefix << " making a new #{model.name} and setting "
@@ -988,7 +992,10 @@ different altogether.
988
992
  MESSAGE
989
993
  end
990
994
 
991
- def description_for_attribute_setter(attribute_setter, same_as_existing: nil)
995
+ def description_for_attribute_setter(
996
+ attribute_setter,
997
+ same_as_existing: nil
998
+ )
992
999
  description = "its :#{attribute_setter.attribute_name} to "
993
1000
 
994
1001
  if same_as_existing == false
@@ -996,13 +1003,13 @@ different altogether.
996
1003
  end
997
1004
 
998
1005
  description << Shoulda::Matchers::Util.inspect_value(
999
- attribute_setter.value_written
1006
+ attribute_setter.value_written,
1000
1007
  )
1001
1008
 
1002
1009
  if attribute_setter.attribute_changed_value?
1003
1010
  description << ' (read back as '
1004
1011
  description << Shoulda::Matchers::Util.inspect_value(
1005
- attribute_setter.value_read
1012
+ attribute_setter.value_read,
1006
1013
  )
1007
1014
  description << ')'
1008
1015
  end
@@ -1026,7 +1033,7 @@ different altogether.
1026
1033
  )
1027
1034
  description_for_attribute_setter(
1028
1035
  attribute_setter,
1029
- same_as_existing: same_as_existing
1036
+ same_as_existing: same_as_existing,
1030
1037
  )
1031
1038
  end
1032
1039
  end
@@ -1109,7 +1116,7 @@ b) If you meant for the validation to be case-insensitive, then you need to
1109
1116
 
1110
1117
  For more information, please see:
1111
1118
 
1112
- http://matchers.shoulda.io/docs/v#{Shoulda::Matchers::VERSION}/file.NonCaseSwappableValueError.html
1119
+ https://matchers.shoulda.io/docs/v#{Shoulda::Matchers::VERSION}/file.NonCaseSwappableValueError.html
1113
1120
  MESSAGE
1114
1121
  end
1115
1122
  end
@@ -1,4 +1,5 @@
1
1
  require 'forwardable'
2
+ require 'logger'
2
3
 
3
4
  module Shoulda
4
5
  module Matchers
@@ -20,7 +21,7 @@ module Shoulda
20
21
 
21
22
  def debug(&block)
22
23
  if debugging_enabled?
23
- puts block.call
24
+ puts block.call # rubocop:disable Rails/Output
24
25
  end
25
26
  end
26
27
  end
@@ -82,7 +82,7 @@ module Shoulda
82
82
  method_name: _method_name,
83
83
  args: args,
84
84
  block: block,
85
- caller: caller
85
+ caller: caller,
86
86
  )
87
87
  implementation.call(call)
88
88
  end
@@ -18,19 +18,19 @@ module Shoulda
18
18
  end
19
19
 
20
20
  def activate
21
- doubles_by_method_name.each do |method_name, double|
21
+ doubles_by_method_name.each do |_method_name, double|
22
22
  double.activate
23
23
  end
24
24
  end
25
25
 
26
26
  def deactivate
27
- doubles_by_method_name.each do |method_name, double|
27
+ doubles_by_method_name.each do |_method_name, double|
28
28
  double.deactivate
29
29
  end
30
30
  end
31
31
 
32
32
  def calls_by_method_name
33
- doubles_by_method_name.reduce({}) do |hash, (method_name, double)|
33
+ doubles_by_method_name.inject({}) do |hash, (method_name, double)|
34
34
  hash.merge method_name => double.calls.map(&:args)
35
35
  end
36
36
  end
@@ -4,23 +4,26 @@ module Shoulda
4
4
  # @private
5
5
  module DoubleImplementationRegistry
6
6
  class << self
7
- REGISTRY = {}
8
-
9
7
  def find(type)
10
8
  find_class!(type).create
11
9
  end
12
10
 
13
11
  def register(klass, type)
14
- REGISTRY[type] = klass
12
+ registry[type] = klass
15
13
  end
16
14
 
17
15
  private
18
16
 
19
17
  def find_class!(type)
20
- REGISTRY.fetch(type) do
21
- raise ArgumentError, "No double implementation class found for '#{type}'"
18
+ registry.fetch(type) do
19
+ raise ArgumentError, 'No double implementation class found for'\
20
+ " '#{type}'"
22
21
  end
23
22
  end
23
+
24
+ def registry
25
+ @_registry ||= {}
26
+ end
24
27
  end
25
28
  end
26
29
  end