giga-safe-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.
- checksums.yaml +7 -0
- data/giga-safe-box.gemspec +11 -0
- data/shoulda-matchers-8.0.1/LICENSE +22 -0
- data/shoulda-matchers-8.0.1/README.md +567 -0
- data/shoulda-matchers-8.0.1/docs/errors/NonCaseSwappableValueError.md +111 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/callback_matcher.rb +121 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +70 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/flash_store.rb +86 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/permit_matcher.rb +445 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +96 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_template_matcher.rb +84 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +145 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +115 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +148 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_matcher.rb +207 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/route_params.rb +62 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/session_store.rb +34 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +228 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_matcher.rb +163 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +107 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/action_controller.rb +24 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +45 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error.rb +23 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +232 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +62 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +40 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +48 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_check.rb +14 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher/successful_setting.rb +14 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/allow_value_matcher.rb +695 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/comparison_matcher.rb +157 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +78 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/errors.rb +52 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +125 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/helpers.rb +37 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +45 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +67 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +45 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +44 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/range_matcher.rb +71 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers/submatchers.rb +53 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb +26 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/allow_nil.rb +26 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignore_interference_by_writer.rb +101 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +21 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/qualifiers.rb +14 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +180 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +128 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_comparison_of_matcher.rb +567 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +185 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +272 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +664 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +575 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +711 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +428 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +62 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_matcher.rb +195 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validation_message_finder.rb +63 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validator.rb +127 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model.rb +96 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +217 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matcher.rb +2134 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +74 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +62 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +41 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +105 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +101 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +89 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +142 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +71 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +41 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +76 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +42 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +65 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +784 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/encrypt_matcher.rb +174 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_attached_matcher.rb +343 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +366 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +287 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +104 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +95 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +83 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +132 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/normalize_matcher.rb +151 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/serialize_matcher.rb +203 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/model.rb +58 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/namespace.rb +39 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +49 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +55 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/uniqueness.rb +14 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +1197 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_record.rb +37 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/configuration.rb +31 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double.rb +103 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_collection.rb +60 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +31 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/method_call.rb +44 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/object_double.rb +43 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +32 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/stub_implementation.rb +31 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak/world.rb +63 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/doublespeak.rb +38 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/error.rb +29 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher/target_not_defined_error.rb +15 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent/delegate_method_matcher.rb +540 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/independent.rb +11 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration.rb +70 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/configuration_error.rb +9 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/inclusion.rb +20 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/action_controller.rb +33 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_model.rb +26 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/active_record.rb +26 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/missing_library.rb +19 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/rails.rb +31 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries/routing.rb +29 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/libraries.rb +16 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/rails.rb +12 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/registry.rb +28 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +37 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +36 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +37 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +40 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/rspec.rb +29 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +36 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations/test_frameworks.rb +16 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/integrations.rb +43 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_collection.rb +99 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/matcher_context.rb +36 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/rails_shim.rb +190 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/routing.rb +10 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util/word_wrap.rb +211 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/util.rb +110 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/version.rb +6 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers/warn.rb +28 -0
- data/shoulda-matchers-8.0.1/lib/shoulda/matchers.rb +25 -0
- data/shoulda-matchers-8.0.1/lib/shoulda-matchers.rb +1 -0
- data/shoulda-matchers-8.0.1/shoulda-matchers.gemspec +43 -0
- metadata +178 -0
data/shoulda-matchers-8.0.1/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb
ADDED
|
@@ -0,0 +1,664 @@
|
|
|
1
|
+
require 'bigdecimal'
|
|
2
|
+
require 'date'
|
|
3
|
+
|
|
4
|
+
module Shoulda
|
|
5
|
+
module Matchers
|
|
6
|
+
# @private
|
|
7
|
+
class ExampleClass; end
|
|
8
|
+
|
|
9
|
+
module ActiveModel
|
|
10
|
+
# The `validate_inclusion_of` matcher tests usage of the
|
|
11
|
+
# `validates_inclusion_of` validation, asserting that an attribute can
|
|
12
|
+
# take a allowlist of values and cannot take values outside of this list.
|
|
13
|
+
#
|
|
14
|
+
# If your allowlist is an array of values, use `in_array`:
|
|
15
|
+
#
|
|
16
|
+
# class Issue
|
|
17
|
+
# include ActiveModel::Model
|
|
18
|
+
# attr_accessor :state
|
|
19
|
+
#
|
|
20
|
+
# validates_inclusion_of :state,
|
|
21
|
+
# in: ['open', 'resolved', 'unresolved']
|
|
22
|
+
# end
|
|
23
|
+
#
|
|
24
|
+
# # RSpec
|
|
25
|
+
# RSpec.describe Issue, type: :model do
|
|
26
|
+
# it do
|
|
27
|
+
# should validate_inclusion_of(:state).
|
|
28
|
+
# in_array(['open', 'resolved', 'unresolved'])
|
|
29
|
+
# end
|
|
30
|
+
# end
|
|
31
|
+
#
|
|
32
|
+
# # Minitest (Shoulda)
|
|
33
|
+
# class IssueTest < ActiveSupport::TestCase
|
|
34
|
+
# should validate_inclusion_of(:state).
|
|
35
|
+
# in_array(['open', 'resolved', 'unresolved'])
|
|
36
|
+
# end
|
|
37
|
+
#
|
|
38
|
+
# If your allowlist is a range of values, use `in_range`:
|
|
39
|
+
#
|
|
40
|
+
# class Issue
|
|
41
|
+
# include ActiveModel::Model
|
|
42
|
+
# attr_accessor :priority
|
|
43
|
+
#
|
|
44
|
+
# validates_inclusion_of :priority, in: 1..5
|
|
45
|
+
# end
|
|
46
|
+
#
|
|
47
|
+
# # RSpec
|
|
48
|
+
# RSpec.describe Issue, type: :model do
|
|
49
|
+
# it { should validate_inclusion_of(:priority).in_range(1..5) }
|
|
50
|
+
# end
|
|
51
|
+
#
|
|
52
|
+
# # Minitest (Shoulda)
|
|
53
|
+
# class IssueTest < ActiveSupport::TestCase
|
|
54
|
+
# should validate_inclusion_of(:priority).in_range(1..5)
|
|
55
|
+
# end
|
|
56
|
+
#
|
|
57
|
+
# #### Caveats
|
|
58
|
+
#
|
|
59
|
+
# We discourage using `validate_inclusion_of` with boolean columns. In
|
|
60
|
+
# fact, there is never a case where a boolean column will be anything but
|
|
61
|
+
# true, false, or nil, as ActiveRecord will type-cast an incoming value to
|
|
62
|
+
# one of these three values. That means there isn't any way we can refute
|
|
63
|
+
# this logic in a test. Hence, this will produce a warning:
|
|
64
|
+
#
|
|
65
|
+
# it do
|
|
66
|
+
# should validate_inclusion_of(:imported).
|
|
67
|
+
# in_array([true, false])
|
|
68
|
+
# end
|
|
69
|
+
#
|
|
70
|
+
# The only case where `validate_inclusion_of` *could* be appropriate is
|
|
71
|
+
# for ensuring that a boolean column accepts nil, but we recommend
|
|
72
|
+
# using `allow_value` instead, like this:
|
|
73
|
+
#
|
|
74
|
+
# it { should allow_value(nil).for(:imported) }
|
|
75
|
+
#
|
|
76
|
+
# #### Qualifiers
|
|
77
|
+
#
|
|
78
|
+
# Use `on` if your validation applies only under a certain context.
|
|
79
|
+
#
|
|
80
|
+
# class Issue
|
|
81
|
+
# include ActiveModel::Model
|
|
82
|
+
# attr_accessor :severity
|
|
83
|
+
#
|
|
84
|
+
# validates_inclusion_of :severity,
|
|
85
|
+
# in: %w(low medium high),
|
|
86
|
+
# on: :create
|
|
87
|
+
# end
|
|
88
|
+
#
|
|
89
|
+
# # RSpec
|
|
90
|
+
# RSpec.describe Issue, type: :model do
|
|
91
|
+
# it do
|
|
92
|
+
# should validate_inclusion_of(:severity).
|
|
93
|
+
# in_array(%w(low medium high)).
|
|
94
|
+
# on(:create)
|
|
95
|
+
# end
|
|
96
|
+
# end
|
|
97
|
+
#
|
|
98
|
+
# # Minitest (Shoulda)
|
|
99
|
+
# class IssueTest < ActiveSupport::TestCase
|
|
100
|
+
# should validate_inclusion_of(:severity).
|
|
101
|
+
# in_array(%w(low medium high)).
|
|
102
|
+
# on(:create)
|
|
103
|
+
# end
|
|
104
|
+
#
|
|
105
|
+
# ##### with_message
|
|
106
|
+
#
|
|
107
|
+
# Use `with_message` if you are using a custom validation message.
|
|
108
|
+
#
|
|
109
|
+
# class Issue
|
|
110
|
+
# include ActiveModel::Model
|
|
111
|
+
# attr_accessor :severity
|
|
112
|
+
#
|
|
113
|
+
# validates_inclusion_of :severity,
|
|
114
|
+
# in: %w(low medium high),
|
|
115
|
+
# message: 'Severity must be low, medium, or high'
|
|
116
|
+
# end
|
|
117
|
+
#
|
|
118
|
+
# # RSpec
|
|
119
|
+
# RSpec.describe Issue, type: :model do
|
|
120
|
+
# it do
|
|
121
|
+
# should validate_inclusion_of(:severity).
|
|
122
|
+
# in_array(%w(low medium high)).
|
|
123
|
+
# with_message('Severity must be low, medium, or high')
|
|
124
|
+
# end
|
|
125
|
+
# end
|
|
126
|
+
#
|
|
127
|
+
# # Minitest (Shoulda)
|
|
128
|
+
# class IssueTest < ActiveSupport::TestCase
|
|
129
|
+
# should validate_inclusion_of(:severity).
|
|
130
|
+
# in_array(%w(low medium high)).
|
|
131
|
+
# with_message('Severity must be low, medium, or high')
|
|
132
|
+
# end
|
|
133
|
+
#
|
|
134
|
+
# ##### with_low_message
|
|
135
|
+
#
|
|
136
|
+
# Use `with_low_message` if you have a custom validation message for when
|
|
137
|
+
# a given value is too low.
|
|
138
|
+
#
|
|
139
|
+
# class Person
|
|
140
|
+
# include ActiveModel::Model
|
|
141
|
+
# attr_accessor :age
|
|
142
|
+
#
|
|
143
|
+
# validate :age_must_be_valid
|
|
144
|
+
#
|
|
145
|
+
# private
|
|
146
|
+
#
|
|
147
|
+
# def age_must_be_valid
|
|
148
|
+
# if age < 65
|
|
149
|
+
# self.errors.add :age, 'You do not receive any benefits'
|
|
150
|
+
# end
|
|
151
|
+
# end
|
|
152
|
+
# end
|
|
153
|
+
#
|
|
154
|
+
# # RSpec
|
|
155
|
+
# RSpec.describe Person, type: :model do
|
|
156
|
+
# it do
|
|
157
|
+
# should validate_inclusion_of(:age).
|
|
158
|
+
# in_range(0..65).
|
|
159
|
+
# with_low_message('You do not receive any benefits')
|
|
160
|
+
# end
|
|
161
|
+
# end
|
|
162
|
+
#
|
|
163
|
+
# # Minitest (Shoulda)
|
|
164
|
+
# class PersonTest < ActiveSupport::TestCase
|
|
165
|
+
# should validate_inclusion_of(:age).
|
|
166
|
+
# in_range(0..65).
|
|
167
|
+
# with_low_message('You do not receive any benefits')
|
|
168
|
+
# end
|
|
169
|
+
#
|
|
170
|
+
# ##### with_high_message
|
|
171
|
+
#
|
|
172
|
+
# Use `with_high_message` if you have a custom validation message for
|
|
173
|
+
# when a given value is too high.
|
|
174
|
+
#
|
|
175
|
+
# class Person
|
|
176
|
+
# include ActiveModel::Model
|
|
177
|
+
# attr_accessor :age
|
|
178
|
+
#
|
|
179
|
+
# validate :age_must_be_valid
|
|
180
|
+
#
|
|
181
|
+
# private
|
|
182
|
+
#
|
|
183
|
+
# def age_must_be_valid
|
|
184
|
+
# if age > 21
|
|
185
|
+
# self.errors.add :age, "You're too old for this stuff"
|
|
186
|
+
# end
|
|
187
|
+
# end
|
|
188
|
+
# end
|
|
189
|
+
#
|
|
190
|
+
# # RSpec
|
|
191
|
+
# RSpec.describe Person, type: :model do
|
|
192
|
+
# it do
|
|
193
|
+
# should validate_inclusion_of(:age).
|
|
194
|
+
# in_range(0..21).
|
|
195
|
+
# with_high_message("You're too old for this stuff")
|
|
196
|
+
# end
|
|
197
|
+
# end
|
|
198
|
+
#
|
|
199
|
+
# # Minitest (Shoulda)
|
|
200
|
+
# class PersonTest < ActiveSupport::TestCase
|
|
201
|
+
# should validate_inclusion_of(:age).
|
|
202
|
+
# in_range(0..21).
|
|
203
|
+
# with_high_message("You're too old for this stuff")
|
|
204
|
+
# end
|
|
205
|
+
#
|
|
206
|
+
# ##### allow_nil
|
|
207
|
+
#
|
|
208
|
+
# Use `allow_nil` to assert that the attribute allows nil.
|
|
209
|
+
#
|
|
210
|
+
# class Issue
|
|
211
|
+
# include ActiveModel::Model
|
|
212
|
+
# attr_accessor :state
|
|
213
|
+
#
|
|
214
|
+
# validates_presence_of :state
|
|
215
|
+
# validates_inclusion_of :state,
|
|
216
|
+
# in: ['open', 'resolved', 'unresolved'],
|
|
217
|
+
# allow_nil: true
|
|
218
|
+
# end
|
|
219
|
+
#
|
|
220
|
+
# # RSpec
|
|
221
|
+
# RSpec.describe Issue, type: :model do
|
|
222
|
+
# it do
|
|
223
|
+
# should validate_inclusion_of(:state).
|
|
224
|
+
# in_array(['open', 'resolved', 'unresolved']).
|
|
225
|
+
# allow_nil
|
|
226
|
+
# end
|
|
227
|
+
# end
|
|
228
|
+
#
|
|
229
|
+
# # Minitest (Shoulda)
|
|
230
|
+
# class IssueTest < ActiveSupport::TestCase
|
|
231
|
+
# should validate_inclusion_of(:state).
|
|
232
|
+
# in_array(['open', 'resolved', 'unresolved']).
|
|
233
|
+
# allow_nil
|
|
234
|
+
# end
|
|
235
|
+
#
|
|
236
|
+
# ##### allow_blank
|
|
237
|
+
#
|
|
238
|
+
# Use `allow_blank` to assert that the attribute allows blank.
|
|
239
|
+
#
|
|
240
|
+
# class Issue
|
|
241
|
+
# include ActiveModel::Model
|
|
242
|
+
# attr_accessor :state
|
|
243
|
+
#
|
|
244
|
+
# validates_presence_of :state
|
|
245
|
+
# validates_inclusion_of :state,
|
|
246
|
+
# in: ['open', 'resolved', 'unresolved'],
|
|
247
|
+
# allow_blank: true
|
|
248
|
+
# end
|
|
249
|
+
#
|
|
250
|
+
# # RSpec
|
|
251
|
+
# RSpec.describe Issue, type: :model do
|
|
252
|
+
# it do
|
|
253
|
+
# should validate_inclusion_of(:state).
|
|
254
|
+
# in_array(['open', 'resolved', 'unresolved']).
|
|
255
|
+
# allow_blank
|
|
256
|
+
# end
|
|
257
|
+
# end
|
|
258
|
+
#
|
|
259
|
+
# # Minitest (Shoulda)
|
|
260
|
+
# class IssueTest < ActiveSupport::TestCase
|
|
261
|
+
# should validate_inclusion_of(:state).
|
|
262
|
+
# in_array(['open', 'resolved', 'unresolved']).
|
|
263
|
+
# allow_blank
|
|
264
|
+
# end
|
|
265
|
+
#
|
|
266
|
+
# #### Multiple attributes
|
|
267
|
+
#
|
|
268
|
+
# You can pass multiple attributes to assert that each one has the
|
|
269
|
+
# validation. Any qualifier chained on the matcher is applied to
|
|
270
|
+
# every attribute uniformly.
|
|
271
|
+
#
|
|
272
|
+
# class Article
|
|
273
|
+
# include ActiveModel::Model
|
|
274
|
+
# attr_accessor :status, :category
|
|
275
|
+
#
|
|
276
|
+
# validates_inclusion_of :status, :category, in: %w[draft published]
|
|
277
|
+
# end
|
|
278
|
+
#
|
|
279
|
+
# # RSpec
|
|
280
|
+
# RSpec.describe Article, type: :model do
|
|
281
|
+
# it { should validate_inclusion_of(:status, :category).in_array(%w[draft published]) }
|
|
282
|
+
# end
|
|
283
|
+
#
|
|
284
|
+
# # Minitest (Shoulda)
|
|
285
|
+
# class ArticleTest < ActiveSupport::TestCase
|
|
286
|
+
# should validate_inclusion_of(:status, :category).in_array(%w[draft published])
|
|
287
|
+
# end
|
|
288
|
+
#
|
|
289
|
+
# @return [ValidateInclusionOfMatcher]
|
|
290
|
+
#
|
|
291
|
+
def validate_inclusion_of(*attrs)
|
|
292
|
+
MatcherCollection.build(attrs) { |attr| ValidateInclusionOfMatcher.new(attr) }
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
# @private
|
|
296
|
+
class ValidateInclusionOfMatcher < ValidationMatcher
|
|
297
|
+
BLANK_VALUES = ['', ' ', "\n", "\r", "\t", "\f"].freeze
|
|
298
|
+
ARBITRARY_OUTSIDE_STRING = Shoulda::Matchers::ExampleClass.name
|
|
299
|
+
ARBITRARY_OUTSIDE_INTEGER = 123456789
|
|
300
|
+
ARBITRARY_OUTSIDE_DECIMAL = BigDecimal('0.123456789')
|
|
301
|
+
ARBITRARY_OUTSIDE_DATE = Date.jd(9999999)
|
|
302
|
+
ARBITRARY_OUTSIDE_DATETIME = DateTime.jd(9999999)
|
|
303
|
+
ARBITRARY_OUTSIDE_TIME = Time.at(9999999999)
|
|
304
|
+
|
|
305
|
+
def initialize(attribute)
|
|
306
|
+
super(attribute)
|
|
307
|
+
@options = {}
|
|
308
|
+
@array = nil
|
|
309
|
+
@range = nil
|
|
310
|
+
@minimum = nil
|
|
311
|
+
@maximum = nil
|
|
312
|
+
@low_message = :inclusion
|
|
313
|
+
@high_message = :inclusion
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def in_array(array)
|
|
317
|
+
@array = array
|
|
318
|
+
self
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def in_range(range)
|
|
322
|
+
@range = range
|
|
323
|
+
@minimum = minimum_range_value
|
|
324
|
+
@maximum = maximum_range_value
|
|
325
|
+
self
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def allow_nil
|
|
329
|
+
@options[:allow_nil] = true
|
|
330
|
+
self
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def expects_to_allow_nil?
|
|
334
|
+
@options[:allow_nil]
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def with_message(message)
|
|
338
|
+
if message
|
|
339
|
+
@expects_custom_validation_message = true
|
|
340
|
+
@low_message = message
|
|
341
|
+
@high_message = message
|
|
342
|
+
end
|
|
343
|
+
|
|
344
|
+
self
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
def with_low_message(message)
|
|
348
|
+
if message
|
|
349
|
+
@expects_custom_validation_message = true
|
|
350
|
+
@low_message = message
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
self
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def with_high_message(message)
|
|
357
|
+
if message
|
|
358
|
+
@high_message = message
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
self
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def simple_description
|
|
365
|
+
if @range
|
|
366
|
+
"validate that :#{@attribute} lies inside the range " +
|
|
367
|
+
Shoulda::Matchers::Util.inspect_range(@range)
|
|
368
|
+
else
|
|
369
|
+
description = "validate that :#{@attribute}"
|
|
370
|
+
|
|
371
|
+
description <<
|
|
372
|
+
if @array.length > 1
|
|
373
|
+
" is either #{inspected_array}"
|
|
374
|
+
else
|
|
375
|
+
" is #{inspected_array}"
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
description
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
def matches?(subject)
|
|
383
|
+
super(subject)
|
|
384
|
+
|
|
385
|
+
if @range
|
|
386
|
+
matches_for_range?
|
|
387
|
+
elsif @array
|
|
388
|
+
if matches_for_array?
|
|
389
|
+
true
|
|
390
|
+
else
|
|
391
|
+
@failure_message = "#{@array} doesn't match array in validation"
|
|
392
|
+
false
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def does_not_match?(subject)
|
|
398
|
+
super(subject)
|
|
399
|
+
|
|
400
|
+
if @range
|
|
401
|
+
does_not_match_for_range?
|
|
402
|
+
elsif @array
|
|
403
|
+
if does_not_match_for_array?
|
|
404
|
+
true
|
|
405
|
+
else
|
|
406
|
+
@failure_message = "#{@array} matches array in validation"
|
|
407
|
+
false
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
private
|
|
413
|
+
|
|
414
|
+
def boolean_allows_boolean_message
|
|
415
|
+
<<-EOT.strip
|
|
416
|
+
You are using `validate_inclusion_of` to assert that the column '#{@subject.class.name}##{attribute}'
|
|
417
|
+
allows boolean values and disallows non-boolean ones. Be aware that it
|
|
418
|
+
is not possible to fully test this, as boolean columns will automatically
|
|
419
|
+
convert non-boolean values to boolean ones. Hence, you should consider
|
|
420
|
+
removing this test.
|
|
421
|
+
EOT
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def boolean_allows_nil_message
|
|
425
|
+
<<-EOT.strip
|
|
426
|
+
You are using `validate_inclusion_of` to assert that the column '#{@subject.class.name}##{attribute}'
|
|
427
|
+
allows nil. Be aware that it is not possible to fully test this, as anything other than
|
|
428
|
+
true, false or nil will be converted to false. Hence, you should consider removing this test.
|
|
429
|
+
EOT
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
def minimum_range_value
|
|
433
|
+
@range.begin
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
def maximum_range_value
|
|
437
|
+
if @range.exclude_end?
|
|
438
|
+
@range.end ? (@range.end - 1) : nil
|
|
439
|
+
else
|
|
440
|
+
@range.end
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
def matches_for_range?
|
|
445
|
+
disallows_lower_value &&
|
|
446
|
+
allows_minimum_value &&
|
|
447
|
+
allows_maximum_value &&
|
|
448
|
+
disallows_higher_value
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
def does_not_match_for_range?
|
|
452
|
+
allows_lower_value ||
|
|
453
|
+
disallows_minimum_value ||
|
|
454
|
+
disallows_maximum_value ||
|
|
455
|
+
allows_higher_value
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
def matches_for_array?
|
|
459
|
+
allows_all_values_in_array? &&
|
|
460
|
+
disallows_all_values_outside_of_array? &&
|
|
461
|
+
allows_nil_value? &&
|
|
462
|
+
allow_blank_matches?
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def does_not_match_for_array?
|
|
466
|
+
disallows_any_values_in_array? ||
|
|
467
|
+
allows_any_value_outside_of_array? ||
|
|
468
|
+
disallows_nil_value? ||
|
|
469
|
+
allow_blank_does_not_match?
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
def allows_lower_value
|
|
473
|
+
@minimum &&
|
|
474
|
+
@minimum != 0 &&
|
|
475
|
+
allows_value_of(@minimum - 1, @low_message)
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
def disallows_lower_value
|
|
479
|
+
@minimum.nil? ||
|
|
480
|
+
@minimum == 0 ||
|
|
481
|
+
disallows_value_of(@minimum - 1, @low_message)
|
|
482
|
+
end
|
|
483
|
+
|
|
484
|
+
def allows_minimum_value
|
|
485
|
+
@minimum.nil? || allows_value_of(@minimum, @low_message)
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
def disallows_minimum_value
|
|
489
|
+
@minimum.nil? || disallows_value_of(@minimum, @low_message)
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
def allows_maximum_value
|
|
493
|
+
@maximum.nil? || allows_value_of(@maximum, @high_message)
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
def disallows_maximum_value
|
|
497
|
+
@maximum.nil? || disallows_value_of(@maximum, @high_message)
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
def allows_higher_value
|
|
501
|
+
@maximum.nil? || allows_value_of(@maximum + 1, @high_message)
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
def disallows_higher_value
|
|
505
|
+
@maximum.nil? || disallows_value_of(@maximum + 1, @high_message)
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
def allows_all_values_in_array?
|
|
509
|
+
@array.all? do |value|
|
|
510
|
+
allows_value_of(value, @low_message)
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
def disallows_any_values_in_array?
|
|
515
|
+
@array.any? do |value|
|
|
516
|
+
disallows_value_of(value, @low_message)
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
def allows_any_value_outside_of_array?
|
|
521
|
+
if attribute_type == :boolean
|
|
522
|
+
case @array
|
|
523
|
+
when [false, true], [true, false]
|
|
524
|
+
Shoulda::Matchers.warn boolean_allows_boolean_message
|
|
525
|
+
return true
|
|
526
|
+
when [nil]
|
|
527
|
+
if attribute_column.null
|
|
528
|
+
Shoulda::Matchers.warn boolean_allows_nil_message
|
|
529
|
+
return true
|
|
530
|
+
else
|
|
531
|
+
raise NonNullableBooleanError.create(@attribute)
|
|
532
|
+
end
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
values_outside_of_array.any? do |value|
|
|
537
|
+
allows_value_of(value, @low_message)
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
def disallows_all_values_outside_of_array?
|
|
542
|
+
if attribute_type == :boolean
|
|
543
|
+
case @array
|
|
544
|
+
when [false, true], [true, false]
|
|
545
|
+
Shoulda::Matchers.warn boolean_allows_boolean_message
|
|
546
|
+
return true
|
|
547
|
+
when [nil]
|
|
548
|
+
if attribute_column.null
|
|
549
|
+
Shoulda::Matchers.warn boolean_allows_nil_message
|
|
550
|
+
return true
|
|
551
|
+
else
|
|
552
|
+
raise NonNullableBooleanError.create(@attribute)
|
|
553
|
+
end
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
values_outside_of_array.all? do |value|
|
|
558
|
+
disallows_value_of(value, @low_message)
|
|
559
|
+
end
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
def values_outside_of_array
|
|
563
|
+
if !(@array & outside_values).empty?
|
|
564
|
+
raise CouldNotDetermineValueOutsideOfArray
|
|
565
|
+
else
|
|
566
|
+
outside_values
|
|
567
|
+
end
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
def outside_values
|
|
571
|
+
case attribute_type
|
|
572
|
+
when :boolean
|
|
573
|
+
boolean_outside_values
|
|
574
|
+
when :integer
|
|
575
|
+
[ARBITRARY_OUTSIDE_INTEGER]
|
|
576
|
+
when :decimal
|
|
577
|
+
[ARBITRARY_OUTSIDE_DECIMAL]
|
|
578
|
+
when :date
|
|
579
|
+
[ARBITRARY_OUTSIDE_DATE]
|
|
580
|
+
when :datetime
|
|
581
|
+
[ARBITRARY_OUTSIDE_DATETIME]
|
|
582
|
+
when :time
|
|
583
|
+
[ARBITRARY_OUTSIDE_TIME]
|
|
584
|
+
else
|
|
585
|
+
[ARBITRARY_OUTSIDE_STRING]
|
|
586
|
+
end
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
def boolean_outside_values
|
|
590
|
+
values = []
|
|
591
|
+
|
|
592
|
+
values << case @array
|
|
593
|
+
when [true] then false
|
|
594
|
+
when [false] then true
|
|
595
|
+
else raise CouldNotDetermineValueOutsideOfArray
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
if attribute_allows_nil?
|
|
599
|
+
values << nil
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
values
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
def attribute_type
|
|
606
|
+
if attribute_column
|
|
607
|
+
column_type_to_attribute_type(attribute_column.type)
|
|
608
|
+
else
|
|
609
|
+
value_to_attribute_type(@subject.__send__(@attribute))
|
|
610
|
+
end
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
def attribute_allows_nil?
|
|
614
|
+
if attribute_column
|
|
615
|
+
attribute_column.null
|
|
616
|
+
else
|
|
617
|
+
true
|
|
618
|
+
end
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
def attribute_column
|
|
622
|
+
if @subject.class.respond_to?(:columns_hash)
|
|
623
|
+
@subject.class.columns_hash[@attribute.to_s]
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
def column_type_to_attribute_type(type)
|
|
628
|
+
case type
|
|
629
|
+
when :float then :integer
|
|
630
|
+
when :timestamp then :datetime
|
|
631
|
+
else type
|
|
632
|
+
end
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
def value_to_attribute_type(value)
|
|
636
|
+
case value
|
|
637
|
+
when true, false then :boolean
|
|
638
|
+
when BigDecimal then :decimal
|
|
639
|
+
when Integer then :integer
|
|
640
|
+
when Date then :date
|
|
641
|
+
when DateTime then :datetime
|
|
642
|
+
when Time then :time
|
|
643
|
+
else :unknown
|
|
644
|
+
end
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
def allows_nil_value?
|
|
648
|
+
@options[:allow_nil] != true || allows_value_of(nil)
|
|
649
|
+
end
|
|
650
|
+
|
|
651
|
+
def disallows_nil_value?
|
|
652
|
+
@options[:allow_nil] && disallows_value_of(nil)
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
def inspected_array
|
|
656
|
+
Shoulda::Matchers::Util.inspect_values(@array).to_sentence(
|
|
657
|
+
two_words_connector: ' or ',
|
|
658
|
+
last_word_connector: ', or ',
|
|
659
|
+
)
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
end
|
|
663
|
+
end
|
|
664
|
+
end
|