ultra-fast-box 0.0.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.
Files changed (140) hide show
  1. checksums.yaml +7 -0
  2. data/shoulda-matchers-8.0.1/LICENSE +22 -0
  3. data/shoulda-matchers-8.0.1/README.md +567 -0
  4. data/shoulda-matchers-8.0.1/docs/errors/NonCaseSwappableValueError.md +111 -0
  5. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/callback_matcher.rb +121 -0
  6. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +70 -0
  7. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/flash_store.rb +86 -0
  8. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/permit_matcher.rb +445 -0
  9. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +96 -0
  10. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_template_matcher.rb +84 -0
  11. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +145 -0
  12. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +115 -0
  13. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +148 -0
  14. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_matcher.rb +207 -0
  15. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_params.rb +62 -0
  16. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/session_store.rb +34 -0
  17. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +228 -0
  18. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_matcher.rb +163 -0
  19. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +107 -0
  20. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller.rb +24 -0
  21. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +45 -0
  22. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error.rb +23 -0
  23. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +232 -0
  24. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +62 -0
  25. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +40 -0
  26. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +48 -0
  27. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_check.rb +14 -0
  28. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_setting.rb +14 -0
  29. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher.rb +695 -0
  30. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/comparison_matcher.rb +157 -0
  31. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +78 -0
  32. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/errors.rb +52 -0
  33. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +125 -0
  34. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/helpers.rb +37 -0
  35. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +45 -0
  36. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +67 -0
  37. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +45 -0
  38. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +44 -0
  39. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb +71 -0
  40. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb +53 -0
  41. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
  42. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb +26 -0
  43. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_nil.rb +26 -0
  44. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignore_interference_by_writer.rb +101 -0
  45. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +21 -0
  46. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers.rb +14 -0
  47. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +180 -0
  48. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +128 -0
  49. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_comparison_of_matcher.rb +567 -0
  50. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +185 -0
  51. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +272 -0
  52. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +664 -0
  53. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +575 -0
  54. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +711 -0
  55. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +428 -0
  56. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +62 -0
  57. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher.rb +195 -0
  58. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_message_finder.rb +63 -0
  59. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validator.rb +127 -0
  60. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model.rb +96 -0
  61. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +217 -0
  62. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matcher.rb +2134 -0
  63. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +74 -0
  64. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +62 -0
  65. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +41 -0
  66. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +105 -0
  67. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +101 -0
  68. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +89 -0
  69. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +142 -0
  70. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +71 -0
  71. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
  72. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +76 -0
  73. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +42 -0
  74. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +65 -0
  75. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
  76. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +784 -0
  77. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/encrypt_matcher.rb +174 -0
  78. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_attached_matcher.rb +343 -0
  79. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +366 -0
  80. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +287 -0
  81. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +104 -0
  82. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +95 -0
  83. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +83 -0
  84. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +132 -0
  85. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/normalize_matcher.rb +151 -0
  86. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/serialize_matcher.rb +203 -0
  87. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/model.rb +58 -0
  88. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/namespace.rb +39 -0
  89. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +49 -0
  90. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +55 -0
  91. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness.rb +14 -0
  92. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +1197 -0
  93. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record.rb +37 -0
  94. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/configuration.rb +31 -0
  95. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double.rb +103 -0
  96. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_collection.rb +60 -0
  97. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +31 -0
  98. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/method_call.rb +44 -0
  99. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/object_double.rb +43 -0
  100. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +32 -0
  101. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/stub_implementation.rb +31 -0
  102. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/world.rb +63 -0
  103. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak.rb +38 -0
  104. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/error.rb +29 -0
  105. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher/target_not_defined_error.rb +15 -0
  106. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher.rb +540 -0
  107. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent.rb +11 -0
  108. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration.rb +70 -0
  109. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration_error.rb +9 -0
  110. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/inclusion.rb +20 -0
  111. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/action_controller.rb +33 -0
  112. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_model.rb +26 -0
  113. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_record.rb +26 -0
  114. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/missing_library.rb +19 -0
  115. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/rails.rb +31 -0
  116. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/routing.rb +29 -0
  117. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries.rb +16 -0
  118. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/rails.rb +12 -0
  119. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/registry.rb +28 -0
  120. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +37 -0
  121. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +36 -0
  122. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +37 -0
  123. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +40 -0
  124. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +29 -0
  125. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +36 -0
  126. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks.rb +16 -0
  127. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations.rb +43 -0
  128. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_collection.rb +99 -0
  129. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_context.rb +36 -0
  130. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/rails_shim.rb +190 -0
  131. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/routing.rb +10 -0
  132. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util/word_wrap.rb +211 -0
  133. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util.rb +110 -0
  134. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/version.rb +6 -0
  135. data/shoulda-matchers-8.0.1/lib/shoulda/matchers/warn.rb +28 -0
  136. data/shoulda-matchers-8.0.1/lib/shoulda/matchers.rb +25 -0
  137. data/shoulda-matchers-8.0.1/lib/shoulda-matchers.rb +1 -0
  138. data/shoulda-matchers-8.0.1/shoulda-matchers.gemspec +43 -0
  139. data/ultra-fast-box.gemspec +12 -0
  140. metadata +179 -0
@@ -0,0 +1,203 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ # The `serialize` matcher tests usage of the `serialize` macro.
5
+ #
6
+ # class Product < ActiveRecord::Base
7
+ # serialize :customizations
8
+ # end
9
+ #
10
+ # # RSpec
11
+ # RSpec.describe Product, type: :model do
12
+ # it { should serialize(:customizations) }
13
+ # end
14
+ #
15
+ # # Minitest (Shoulda)
16
+ # class ProductTest < ActiveSupport::TestCase
17
+ # should serialize(:customizations)
18
+ # end
19
+ #
20
+ # #### Qualifiers
21
+ #
22
+ # ##### as
23
+ #
24
+ # Use `as` if you are using a custom serializer class.
25
+ #
26
+ # class ProductSpecsSerializer
27
+ # def load(string)
28
+ # # ...
29
+ # end
30
+ #
31
+ # def dump(options)
32
+ # # ...
33
+ # end
34
+ # end
35
+ #
36
+ # class Product < ActiveRecord::Base
37
+ # serialize :specifications, ProductSpecsSerializer
38
+ # end
39
+ #
40
+ # # RSpec
41
+ # RSpec.describe Product, type: :model do
42
+ # it do
43
+ # should serialize(:specifications).
44
+ # as(ProductSpecsSerializer)
45
+ # end
46
+ # end
47
+ #
48
+ # # Minitest (Shoulda)
49
+ # class ProductTest < ActiveSupport::TestCase
50
+ # should serialize(:specifications).
51
+ # as(ProductSpecsSerializer)
52
+ # end
53
+ #
54
+ # ##### as_instance_of
55
+ #
56
+ # Use `as_instance_of` if you are using a custom serializer object.
57
+ #
58
+ # class ProductOptionsSerializer
59
+ # def load(string)
60
+ # # ...
61
+ # end
62
+ #
63
+ # def dump(options)
64
+ # # ...
65
+ # end
66
+ # end
67
+ #
68
+ # class Product < ActiveRecord::Base
69
+ # serialize :options, ProductOptionsSerializer.new
70
+ # end
71
+ #
72
+ # # RSpec
73
+ # RSpec.describe Product, type: :model do
74
+ # it do
75
+ # should serialize(:options).
76
+ # as_instance_of(ProductOptionsSerializer)
77
+ # end
78
+ # end
79
+ #
80
+ # # Minitest (Shoulda)
81
+ # class ProductTest < ActiveSupport::TestCase
82
+ # should serialize(:options).
83
+ # as_instance_of(ProductOptionsSerializer)
84
+ # end
85
+ #
86
+ # @return [SerializeMatcher]
87
+ #
88
+ def serialize(name)
89
+ SerializeMatcher.new(name)
90
+ end
91
+
92
+ # @private
93
+ class SerializeMatcher
94
+ def initialize(name)
95
+ @name = name.to_s
96
+ @options = {}
97
+ end
98
+
99
+ def as(type)
100
+ @options[:type] = type
101
+ self
102
+ end
103
+
104
+ def as_instance_of(type)
105
+ @options[:instance_type] = type
106
+ self
107
+ end
108
+
109
+ def matches?(subject)
110
+ @subject = subject
111
+ serialization_valid? && type_valid?
112
+ end
113
+
114
+ def failure_message
115
+ "Expected #{expectation} (#{@missing})"
116
+ end
117
+
118
+ def failure_message_when_negated
119
+ "Did not expect #{expectation}"
120
+ end
121
+
122
+ def description
123
+ description = "serialize :#{@name}"
124
+ if @options.key?(:type)
125
+ description += " class_name => #{@options[:type]}"
126
+ end
127
+ description
128
+ end
129
+
130
+ protected
131
+
132
+ def serialization_valid?
133
+ if attribute_is_serialized?
134
+ true
135
+ else
136
+ @missing = "no serialized attribute called :#{@name}"
137
+ false
138
+ end
139
+ end
140
+
141
+ def class_valid?
142
+ if @options[:type]
143
+ klass = serialization_coder
144
+ if klass == @options[:type]
145
+ true
146
+ elsif klass.respond_to?(:object_class) &&
147
+ klass.object_class == @options[:type]
148
+ true
149
+ else
150
+ @missing = ":#{@name} should be a type of #{@options[:type]}"
151
+ false
152
+ end
153
+ else
154
+ true
155
+ end
156
+ end
157
+
158
+ def model_class
159
+ @subject.class
160
+ end
161
+
162
+ def instance_class_valid?
163
+ if @options.key?(:instance_type)
164
+ if serialization_coder.is_a?(@options[:instance_type])
165
+ true
166
+ else
167
+ @missing = ":#{@name} should be an instance of #{@options[:type]}"
168
+ false
169
+ end
170
+ else
171
+ true
172
+ end
173
+ end
174
+
175
+ def type_valid?
176
+ class_valid? && instance_class_valid?
177
+ end
178
+
179
+ def expectation
180
+ expectation = "#{model_class.name} to serialize the attribute called"\
181
+ " :#{@name}"
182
+ expectation += " with a type of #{@options[:type]}" if @options[:type]
183
+ if @options[:instance_type]
184
+ expectation += " with an instance of #{@options[:instance_type]}"
185
+ end
186
+ expectation
187
+ end
188
+
189
+ def attribute_is_serialized?
190
+ !!serialization_coder
191
+ end
192
+
193
+ def serialization_coder
194
+ RailsShim.attribute_serialization_coder_for(model, @name)
195
+ end
196
+
197
+ def model
198
+ @subject.class
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
@@ -0,0 +1,58 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ # @private
5
+ module Uniqueness
6
+ # @private
7
+ class Model
8
+ def self.next_unique_copy_of(model_name, namespace)
9
+ model = new(model_name, namespace)
10
+
11
+ while model.already_exists?
12
+ model = model.next
13
+ end
14
+
15
+ model
16
+ end
17
+
18
+ def initialize(name, namespace)
19
+ @name = name
20
+ @namespace = namespace
21
+ end
22
+
23
+ def already_exists?
24
+ namespace.has?(name)
25
+ end
26
+
27
+ def next
28
+ Model.new(name.next, namespace)
29
+ end
30
+
31
+ def symlink_to(parent)
32
+ table_name = parent.table_name
33
+
34
+ new_class = Class.new(parent) do
35
+ define_singleton_method :table_name do
36
+ table_name
37
+ end
38
+
39
+ define_singleton_method :base_class do
40
+ self
41
+ end
42
+ end
43
+
44
+ namespace.set(name, new_class)
45
+ end
46
+
47
+ def to_s
48
+ [namespace, name].join('::')
49
+ end
50
+
51
+ protected
52
+
53
+ attr_reader :name, :namespace
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,39 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ # @private
5
+ module Uniqueness
6
+ # @private
7
+ class Namespace
8
+ def initialize(constant)
9
+ @constant = constant
10
+ end
11
+
12
+ def has?(name)
13
+ constant.const_defined?(name, false)
14
+ end
15
+
16
+ def set(name, value)
17
+ constant.const_set(name, value)
18
+ end
19
+
20
+ def clear
21
+ constant.constants.each do |child_constant|
22
+ constant.remove_const(child_constant)
23
+ rescue NameError
24
+ # Constant may have been removed elsewhere; ignore
25
+ end
26
+ end
27
+
28
+ def to_s
29
+ constant.to_s
30
+ end
31
+
32
+ protected
33
+
34
+ attr_reader :constant
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,49 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ # @private
5
+ module Uniqueness
6
+ # @private
7
+ class TestModelCreator
8
+ def self.create(model_name, namespace)
9
+ Mutex.new.synchronize do
10
+ new(model_name, namespace).create
11
+ end
12
+ end
13
+
14
+ def initialize(model_name, namespace)
15
+ @model_name = model_name
16
+ @namespace = namespace
17
+ end
18
+
19
+ def create
20
+ new_model.tap do |new_model|
21
+ new_model.symlink_to(existing_model)
22
+ end
23
+ end
24
+
25
+ protected
26
+
27
+ attr_reader :model_name, :namespace
28
+
29
+ private
30
+
31
+ def model_name_without_namespace
32
+ model_name.demodulize
33
+ end
34
+
35
+ def new_model
36
+ @_new_model ||= Model.next_unique_copy_of(
37
+ model_name_without_namespace,
38
+ namespace,
39
+ )
40
+ end
41
+
42
+ def existing_model
43
+ @_existing_model ||= model_name.constantize
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,55 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ # @private
5
+ module Uniqueness
6
+ # @private
7
+ module TestModels
8
+ # Test models subclass real ActiveRecord models, so they register
9
+ # in `descendants`/`subclasses` and cannot be unregistered after
10
+ # the fact: ActiveSupport::DescendantsTracker.clear raises when
11
+ # config.enable_reloading is false (the default in the test
12
+ # environment), and the classes cannot be reliably garbage
13
+ # collected. Instead, mirror the filtering technique Rails itself
14
+ # uses for reloaded classes and hide them at the source.
15
+ module DescendantsFiltering
16
+ def descendants
17
+ super.reject { |klass| TestModels.contains?(klass) }
18
+ end
19
+
20
+ def subclasses
21
+ super.reject { |klass| TestModels.contains?(klass) }
22
+ end
23
+ end
24
+
25
+ def self.create(model_name)
26
+ hide_from_descendants
27
+ TestModelCreator.create(model_name, root_namespace)
28
+ end
29
+
30
+ def self.remove_all
31
+ root_namespace.clear
32
+ end
33
+
34
+ def self.root_namespace
35
+ @_root_namespace ||= Namespace.new(self)
36
+ end
37
+
38
+ def self.contains?(klass)
39
+ !klass.name.nil? && klass.name.start_with?(name_prefix)
40
+ end
41
+
42
+ def self.name_prefix
43
+ @_name_prefix ||= "#{name}::"
44
+ end
45
+
46
+ def self.hide_from_descendants
47
+ @_hide_from_descendants ||=
48
+ ::ActiveRecord::Base.singleton_class.
49
+ prepend(DescendantsFiltering) && true
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,14 @@
1
+ module Shoulda
2
+ module Matchers
3
+ module ActiveRecord
4
+ # @private
5
+ module Uniqueness
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+ require 'shoulda/matchers/active_record/uniqueness/model'
12
+ require 'shoulda/matchers/active_record/uniqueness/namespace'
13
+ require 'shoulda/matchers/active_record/uniqueness/test_model_creator'
14
+ require 'shoulda/matchers/active_record/uniqueness/test_models'