shoulda-matchers 2.6.1 → 2.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +9 -0
- data/.yardopts +8 -0
- data/Appraisals +82 -33
- data/Gemfile +18 -2
- data/Gemfile.lock +13 -1
- data/NEWS.md +27 -2
- data/README.md +83 -1329
- data/Rakefile +118 -1
- data/cucumber.yml +1 -0
- data/doc_config/gh-pages/index.html.erb +9 -0
- data/doc_config/yard/setup.rb +22 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +5967 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +12 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/global.css +45 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +69 -0
- data/doc_config/yard/templates/default/fulldoc/html/css/style.css +283 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +32 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +1 -0
- data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +8 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/app.js +298 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +1 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +289 -0
- data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +6 -0
- data/doc_config/yard/templates/default/fulldoc/html/setup.rb +8 -0
- data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +14 -0
- data/doc_config/yard/templates/default/layout/html/fonts.erb +1 -0
- data/doc_config/yard/templates/default/layout/html/layout.erb +23 -0
- data/doc_config/yard/templates/default/layout/html/search.erb +13 -0
- data/doc_config/yard/templates/default/layout/html/setup.rb +40 -0
- data/doc_config/yard/templates/default/method_details/html/source.erb +10 -0
- data/doc_config/yard/templates/default/module/html/box_info.erb +31 -0
- data/docs.watchr +5 -0
- data/features/rails_integration.feature +32 -0
- data/features/step_definitions/rails_steps.rb +55 -9
- data/features/support/env.rb +1 -0
- data/gemfiles/3.0.gemfile +13 -1
- data/gemfiles/3.0.gemfile.lock +13 -1
- data/gemfiles/3.1.gemfile +17 -2
- data/gemfiles/3.1.gemfile.lock +31 -2
- data/gemfiles/3.1_1.9.2.gemfile +33 -0
- data/gemfiles/3.1_1.9.2.gemfile.lock +203 -0
- data/gemfiles/3.2.gemfile +18 -2
- data/gemfiles/3.2.gemfile.lock +32 -2
- data/gemfiles/3.2_1.9.2.gemfile +32 -0
- data/gemfiles/3.2_1.9.2.gemfile.lock +200 -0
- data/gemfiles/4.0.0.gemfile +20 -1
- data/gemfiles/4.0.0.gemfile.lock +46 -2
- data/gemfiles/4.0.1.gemfile +20 -1
- data/gemfiles/4.0.1.gemfile.lock +46 -2
- data/gemfiles/4.1.gemfile +21 -2
- data/gemfiles/4.1.gemfile.lock +47 -4
- data/lib/shoulda/matchers/action_controller.rb +0 -20
- data/lib/shoulda/matchers/action_controller/callback_matcher.rb +119 -28
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +22 -6
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +43 -10
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +40 -13
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +63 -11
- data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +34 -1
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +84 -15
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +84 -28
- data/lib/shoulda/matchers/action_controller/route_params.rb +4 -3
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +76 -13
- data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +147 -13
- data/lib/shoulda/matchers/action_controller/strong_parameters_matcher.rb +148 -2
- data/lib/shoulda/matchers/active_model.rb +0 -25
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +66 -9
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +161 -19
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +5 -5
- data/lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb +92 -13
- data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +218 -16
- data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +198 -32
- data/lib/shoulda/matchers/active_model/errors.rb +5 -2
- data/lib/shoulda/matchers/active_model/exception_message_finder.rb +1 -1
- data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +29 -8
- data/lib/shoulda/matchers/active_model/helpers.rb +20 -8
- data/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +4 -6
- data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +3 -2
- data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +52 -14
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +51 -13
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +53 -7
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +275 -19
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +84 -14
- data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +170 -41
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +20 -15
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +1 -2
- data/lib/shoulda/matchers/active_record.rb +1 -12
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +89 -15
- data/lib/shoulda/matchers/active_record/association_matcher.rb +726 -70
- data/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
- data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +2 -1
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +4 -5
- data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +4 -3
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +79 -15
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +64 -15
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +21 -7
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +85 -10
- data/lib/shoulda/matchers/assertion_error.rb +7 -1
- data/lib/shoulda/matchers/doublespeak.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/double.rb +3 -1
- data/lib/shoulda/matchers/doublespeak/double_collection.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +1 -0
- data/lib/shoulda/matchers/doublespeak/object_double.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/structs.rb +2 -0
- data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +2 -1
- data/lib/shoulda/matchers/doublespeak/world.rb +3 -4
- data/lib/shoulda/matchers/error.rb +1 -0
- data/lib/shoulda/matchers/independent/delegate_matcher.rb +108 -20
- data/lib/shoulda/matchers/independent/delegate_matcher/stubbed_target.rb +4 -3
- data/lib/shoulda/matchers/integrations/nunit_test_case_detection.rb +3 -0
- data/lib/shoulda/matchers/rails_shim.rb +3 -2
- data/lib/shoulda/matchers/version.rb +2 -1
- data/lib/shoulda/matchers/warn.rb +1 -0
- data/script/SUPPORTED_VERSIONS +1 -0
- data/script/install_gems_in_all_appraisals +14 -0
- data/script/run_all_tests +14 -0
- data/shoulda-matchers.gemspec +0 -10
- data/spec/report_warnings.rb +7 -0
- data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +1 -1
- data/spec/shoulda/matchers/action_controller/strong_parameters_matcher_spec.rb +9 -0
- data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +0 -36
- data/spec/shoulda/matchers/active_model/validation_message_finder_spec.rb +2 -2
- data/spec/shoulda/matchers/doublespeak/double_spec.rb +1 -1
- data/spec/shoulda/matchers/doublespeak/world_spec.rb +11 -29
- data/spec/shoulda/matchers/doublespeak_spec.rb +3 -3
- data/spec/spec_helper.rb +17 -0
- data/spec/support/class_builder.rb +4 -0
- data/spec/support/test_application.rb +1 -1
- data/spec/warnings_spy.rb +64 -0
- data/spec/warnings_spy/filesystem.rb +45 -0
- data/spec/warnings_spy/partitioner.rb +29 -0
- data/spec/warnings_spy/reader.rb +64 -0
- data/spec/warnings_spy/reporter.rb +87 -0
- metadata +49 -134
@@ -22,33 +22,8 @@ require 'shoulda/matchers/active_model/allow_mass_assignment_of_matcher'
|
|
22
22
|
require 'shoulda/matchers/active_model/errors'
|
23
23
|
require 'shoulda/matchers/active_model/have_secure_password_matcher'
|
24
24
|
|
25
|
-
|
26
25
|
module Shoulda
|
27
26
|
module Matchers
|
28
|
-
# = Matchers for your active record models
|
29
|
-
#
|
30
|
-
# These matchers will test most of the validations of ActiveModel::Validations.
|
31
|
-
#
|
32
|
-
# describe User do
|
33
|
-
# it { should validate_presence_of(:name) }
|
34
|
-
# it { should validate_presence_of(:phone_number) }
|
35
|
-
# %w(abcd 1234).each do |value|
|
36
|
-
# it { should_not allow_value(value).for(:phone_number) }
|
37
|
-
# end
|
38
|
-
# it { should allow_value('(123) 456-7890').for(:phone_number) }
|
39
|
-
# it { should_not allow_mass_assignment_of(:password) }
|
40
|
-
# it { should allow_value('Activated', 'Pending').for(:status).strict }
|
41
|
-
# it { should_not allow_value('Amazing').for(:status).strict }
|
42
|
-
# end
|
43
|
-
#
|
44
|
-
# These tests work with the following model:
|
45
|
-
#
|
46
|
-
# class User < ActiveRecord::Base
|
47
|
-
# validates_presence_of :name
|
48
|
-
# validates_presence_of :phone_number
|
49
|
-
# validates_inclusion_of :status, in: %w(Activated Pending), strict: true
|
50
|
-
# attr_accessible :name, :phone_number
|
51
|
-
# end
|
52
27
|
module ActiveModel
|
53
28
|
end
|
54
29
|
end
|
@@ -1,21 +1,78 @@
|
|
1
|
-
module Shoulda
|
1
|
+
module Shoulda
|
2
2
|
module Matchers
|
3
|
-
module ActiveModel
|
4
|
-
|
5
|
-
#
|
3
|
+
module ActiveModel
|
4
|
+
# The `allow_mass_assignment_of` matcher tests usage of Rails 3's
|
5
|
+
# `attr_accessible` and `attr_protected` macros, asserting that an
|
6
|
+
# attribute in your model is contained in either the whitelist or
|
7
|
+
# blacklist and thus can or cannot be set via mass assignment.
|
8
|
+
#
|
9
|
+
# class Post
|
10
|
+
# include ActiveModel::Model
|
11
|
+
# include ActiveModel::MassAssignmentSecurity
|
12
|
+
# attr_accessor :title
|
13
|
+
#
|
14
|
+
# attr_accessible :title
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# class User
|
18
|
+
# include ActiveModel::Model
|
19
|
+
# include ActiveModel::MassAssignmentSecurity
|
20
|
+
# attr_accessor :encrypted_password
|
21
|
+
#
|
22
|
+
# attr_protected :encrypted_password
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# # RSpec
|
26
|
+
# describe Post do
|
27
|
+
# it { should allow_mass_assignment_of(:title) }
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
# describe User do
|
31
|
+
# it { should_not allow_mass_assignment_of(:encrypted_password) }
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# # Test::Unit
|
35
|
+
# class PostTest < ActiveSupport::TestCase
|
36
|
+
# should allow_mass_assignment_of(:title)
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# class UserTest < ActiveSupport::TestCase
|
40
|
+
# should_not allow_mass_assignment_of(:encrypted_password)
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# #### Optional qualifiers
|
44
|
+
#
|
45
|
+
# ##### as
|
46
|
+
#
|
47
|
+
# Use `as` if your mass-assignment rules apply only under a certain role
|
48
|
+
# *(Rails >= 3.1 only)*.
|
49
|
+
#
|
50
|
+
# class Post
|
51
|
+
# include ActiveModel::Model
|
52
|
+
# include ActiveModel::MassAssignmentSecurity
|
53
|
+
# attr_accessor :title
|
54
|
+
#
|
55
|
+
# attr_accessible :title, as: :admin
|
56
|
+
# end
|
6
57
|
#
|
7
|
-
#
|
8
|
-
#
|
58
|
+
# # RSpec
|
59
|
+
# describe Post do
|
60
|
+
# it { should allow_mass_assignment_of(:title).as(:admin) }
|
61
|
+
# end
|
9
62
|
#
|
10
|
-
#
|
63
|
+
# # Test::Unit
|
64
|
+
# class PostTest < ActiveSupport::TestCase
|
65
|
+
# should allow_mass_assignment_of(:title).as(:admin)
|
66
|
+
# end
|
11
67
|
#
|
12
|
-
#
|
68
|
+
# @return [AllowMassAssignmentOfMatcher]
|
13
69
|
#
|
14
70
|
def allow_mass_assignment_of(value)
|
15
71
|
AllowMassAssignmentOfMatcher.new(value)
|
16
72
|
end
|
17
73
|
|
18
|
-
|
74
|
+
# @private
|
75
|
+
class AllowMassAssignmentOfMatcher
|
19
76
|
attr_reader :failure_message, :failure_message_when_negated
|
20
77
|
|
21
78
|
alias failure_message_for_should failure_message
|
@@ -1,23 +1,164 @@
|
|
1
|
-
module Shoulda
|
1
|
+
module Shoulda
|
2
2
|
module Matchers
|
3
|
-
module ActiveModel
|
4
|
-
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
3
|
+
module ActiveModel
|
4
|
+
# The `allow_value` matcher is used to test that an attribute of a model
|
5
|
+
# can or cannot be set to a particular value or values. It is most
|
6
|
+
# commonly used in conjunction with the `validates_format_of` validation.
|
7
|
+
#
|
8
|
+
# #### should
|
9
|
+
#
|
10
|
+
# In the positive form, `allow_value` asserts that an attribute can be
|
11
|
+
# set to one or more values, succeeding if none of the values cause the
|
12
|
+
# record to be invalid:
|
13
|
+
#
|
14
|
+
# class UserProfile
|
15
|
+
# include ActiveModel::Model
|
16
|
+
# attr_accessor :website_url
|
17
|
+
#
|
18
|
+
# validates_format_of :website_url, with: URI.regexp
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# # RSpec
|
22
|
+
# describe UserProfile do
|
23
|
+
# it do
|
24
|
+
# should allow_value('http://foo.com', 'http://bar.com/baz').
|
25
|
+
# for(:website_url)
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# # Test::Unit
|
30
|
+
# class UserProfileTest < ActiveSupport::TestCase
|
31
|
+
# should allow_value('http://foo.com', 'http://bar.com/baz').
|
32
|
+
# for(:website_url)
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# #### should_not
|
36
|
+
#
|
37
|
+
# In the negative form, `allow_value` asserts that an attribute cannot be
|
38
|
+
# set to one or more values, succeeding if the *first* value causes the
|
39
|
+
# record to be invalid.
|
40
|
+
#
|
41
|
+
# **This can be surprising** so in this case if you need to check that
|
42
|
+
# *all* of the values are invalid, use separate assertions:
|
43
|
+
#
|
44
|
+
# class UserProfile
|
45
|
+
# include ActiveModel::Model
|
46
|
+
# attr_accessor :website_url
|
47
|
+
#
|
48
|
+
# validates_format_of :website_url, with: URI.regexp
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# describe UserProfile do
|
52
|
+
# # One assertion: 'buz' and 'bar' will not be tested
|
53
|
+
# it { should_not allow_value('fiz', 'buz', 'bar').for(:website_url) }
|
54
|
+
#
|
55
|
+
# # Three assertions, all tested separately
|
56
|
+
# it { should_not allow_value('fiz').for(:website_url) }
|
57
|
+
# it { should_not allow_value('buz').for(:website_url) }
|
58
|
+
# it { should_not allow_value('bar').for(:website_url) }
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# #### Qualifiers
|
62
|
+
#
|
63
|
+
# ##### on
|
64
|
+
#
|
65
|
+
# Use `on` if your validation applies only under a certain context.
|
66
|
+
#
|
67
|
+
# class UserProfile
|
68
|
+
# include ActiveModel::Model
|
69
|
+
# attr_accessor :birthday_as_string
|
70
|
+
#
|
71
|
+
# validates_format_of :birthday_as_string,
|
72
|
+
# with: /^(\d+)-(\d+)-(\d+)$/,
|
73
|
+
# on: :create
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# # RSpec
|
77
|
+
# describe UserProfile do
|
78
|
+
# it do
|
79
|
+
# should allow_value('2013-01-01').
|
80
|
+
# for(:birthday_as_string).
|
81
|
+
# on(:create)
|
82
|
+
# end
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
# # Test::Unit
|
86
|
+
# class UserProfileTest < ActiveSupport::TestCase
|
87
|
+
# should allow_value('2013-01-01').
|
88
|
+
# for(:birthday_as_string).
|
89
|
+
# on(:create)
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# ##### with_message
|
93
|
+
#
|
94
|
+
# Use `with_message` if you are using a custom validation message.
|
95
|
+
#
|
96
|
+
# class UserProfile
|
97
|
+
# include ActiveModel::Model
|
98
|
+
# attr_accessor :state
|
99
|
+
#
|
100
|
+
# validates_format_of :state,
|
101
|
+
# with: /^(open|closed)$/,
|
102
|
+
# message: 'State must be open or closed'
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
# # RSpec
|
106
|
+
# describe UserProfile do
|
107
|
+
# it do
|
108
|
+
# should allow_value('open', 'closed').
|
109
|
+
# for(:state).
|
110
|
+
# with_message('State must be open or closed')
|
111
|
+
# end
|
112
|
+
# end
|
113
|
+
#
|
114
|
+
# # Test::Unit
|
115
|
+
# class UserProfileTest < ActiveSupport::TestCase
|
116
|
+
# should allow_value('open', 'closed').
|
117
|
+
# for(:state).
|
118
|
+
# with_message('State must be open or closed')
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
# Use `with_message` with the `:against` option if the attribute the
|
122
|
+
# validation message is stored under is different from the attribute
|
123
|
+
# being validated.
|
124
|
+
#
|
125
|
+
# class UserProfile
|
126
|
+
# include ActiveModel::Model
|
127
|
+
# attr_accessor :sports_team
|
128
|
+
#
|
129
|
+
# validate :sports_team_must_be_valid
|
130
|
+
#
|
131
|
+
# private
|
132
|
+
#
|
133
|
+
# def sports_team_must_be_valid
|
134
|
+
# if sports_team !~ /^(Broncos|Titans)$/i
|
135
|
+
# self.errors.add :chosen_sports_team,
|
136
|
+
# 'Must be either a Broncos fan or a Titans fan'
|
137
|
+
# end
|
138
|
+
# end
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# # RSpec
|
142
|
+
# describe UserProfile do
|
143
|
+
# it do
|
144
|
+
# should allow_value('Broncos', 'Titans').
|
145
|
+
# for(:sports_team).
|
146
|
+
# with_message('Must be either a Broncos or Titans fan',
|
147
|
+
# against: :chosen_sports_team
|
148
|
+
# )
|
149
|
+
# end
|
150
|
+
# end
|
9
151
|
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
152
|
+
# # Test::Unit
|
153
|
+
# class UserProfileTest < ActiveSupport::TestCase
|
154
|
+
# should allow_value('Broncos', 'Titans').
|
155
|
+
# for(:sports_team).
|
156
|
+
# with_message('Must be either a Broncos or Titans fan',
|
157
|
+
# against: :chosen_sports_team
|
158
|
+
# )
|
159
|
+
# end
|
17
160
|
#
|
18
|
-
#
|
19
|
-
# it { should_not allow_value('bad').for(:isbn) }
|
20
|
-
# it { should allow_value('isbn 1 2345 6789 0').for(:isbn) }
|
161
|
+
# @return [AllowValueMatcher]
|
21
162
|
#
|
22
163
|
def allow_value(*values)
|
23
164
|
if values.empty?
|
@@ -27,7 +168,8 @@ module Shoulda # :nodoc:
|
|
27
168
|
end
|
28
169
|
end
|
29
170
|
|
30
|
-
|
171
|
+
# @private
|
172
|
+
class AllowValueMatcher
|
31
173
|
include Helpers
|
32
174
|
|
33
175
|
attr_accessor :attribute_with_message
|
@@ -95,7 +237,7 @@ module Shoulda # :nodoc:
|
|
95
237
|
message_finder.allow_description(allowed_values)
|
96
238
|
end
|
97
239
|
|
98
|
-
|
240
|
+
protected
|
99
241
|
|
100
242
|
attr_accessor :values_to_match, :message_finder_factory,
|
101
243
|
:instance, :attribute_to_set, :attribute_to_check_message_against,
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
|
3
|
-
module Shoulda
|
3
|
+
module Shoulda
|
4
4
|
module Matchers
|
5
|
-
module ActiveModel
|
6
|
-
|
5
|
+
module ActiveModel
|
6
|
+
# @private
|
7
|
+
class DisallowValueMatcher
|
7
8
|
extend Forwardable
|
8
9
|
|
9
10
|
def_delegators :allow_matcher, :_after_setting_value
|
10
|
-
|
11
11
|
def initialize(value)
|
12
12
|
@allow_matcher = AllowValueMatcher.new(value)
|
13
13
|
end
|
@@ -46,7 +46,7 @@ module Shoulda # :nodoc:
|
|
46
46
|
self
|
47
47
|
end
|
48
48
|
|
49
|
-
|
49
|
+
protected
|
50
50
|
|
51
51
|
attr_reader :allow_matcher
|
52
52
|
end
|
@@ -1,24 +1,103 @@
|
|
1
|
-
module Shoulda
|
1
|
+
module Shoulda
|
2
2
|
module Matchers
|
3
|
-
module ActiveModel
|
4
|
-
|
5
|
-
#
|
3
|
+
module ActiveModel
|
4
|
+
# The `ensure_exclusion_of` matcher tests usage of the
|
5
|
+
# `validates_exclusion_of` validation, asserting that an attribute cannot
|
6
|
+
# take a blacklist of values, and inversely, can take values outside of
|
7
|
+
# this list.
|
8
|
+
#
|
9
|
+
# If your blacklist is an array of values, use `in_array`:
|
10
|
+
#
|
11
|
+
# class Game
|
12
|
+
# include ActiveModel::Model
|
13
|
+
# attr_accessor :supported_os
|
14
|
+
#
|
15
|
+
# validates_exclusion_of :supported_os, in: ['Mac', 'Linux']
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # RSpec
|
19
|
+
# describe Game do
|
20
|
+
# it do
|
21
|
+
# should ensure_exclusion_of(:supported_os).
|
22
|
+
# in_array(['Mac', 'Linux'])
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
# # Test::Unit
|
27
|
+
# class GameTest < ActiveSupport::TestCase
|
28
|
+
# should ensure_exclusion_of(:supported_os).
|
29
|
+
# in_array(['Mac', 'Linux'])
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# If your blacklist is a range of values, use `in_rnage`:
|
33
|
+
#
|
34
|
+
# class Game
|
35
|
+
# include ActiveModel::Model
|
36
|
+
# attr_accessor :supported_os
|
37
|
+
#
|
38
|
+
# validates_exclusion_of :supported_os, in: ['Mac', 'Linux']
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# # RSpec
|
42
|
+
# describe Game do
|
43
|
+
# it do
|
44
|
+
# should ensure_exclusion_of(:floors_with_enemies).
|
45
|
+
# in_range(5..8)
|
46
|
+
# end
|
47
|
+
# end
|
6
48
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# translation for :exclusion.
|
49
|
+
# # Test::Unit
|
50
|
+
# class GameTest < ActiveSupport::TestCase
|
51
|
+
# should ensure_exclusion_of(:floors_with_enemies).
|
52
|
+
# in_range(5..8)
|
53
|
+
# end
|
13
54
|
#
|
14
|
-
#
|
15
|
-
#
|
55
|
+
# #### Qualifiers
|
56
|
+
#
|
57
|
+
# ##### with_message
|
58
|
+
#
|
59
|
+
# Use `with_message` if you are using a custom validation message.
|
60
|
+
#
|
61
|
+
# class Game
|
62
|
+
# include ActiveModel::Model
|
63
|
+
# attr_accessor :weapon
|
64
|
+
#
|
65
|
+
# validates_exclusion_of :weapon,
|
66
|
+
# in: ['pistol', 'paintball gun', 'stick'],
|
67
|
+
# message: 'You chose a puny weapon'
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# # RSpec
|
71
|
+
# describe Game do
|
72
|
+
# it do
|
73
|
+
# should ensure_exclusion_of(:weapon).
|
74
|
+
# in_array(['pistol', 'paintball gun', 'stick']).
|
75
|
+
# with_message('You chose a puny weapon')
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# # Test::Unit
|
80
|
+
# class GameTest < ActiveSupport::TestCase
|
81
|
+
# should ensure_exclusion_of(:weapon).
|
82
|
+
# in_array(['pistol', 'paintball gun', 'stick']).
|
83
|
+
# with_message('You chose a puny weapon')
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# @return [EnsureExclusionOfMatcher]
|
16
87
|
#
|
17
88
|
def ensure_exclusion_of(attr)
|
18
89
|
EnsureExclusionOfMatcher.new(attr)
|
19
90
|
end
|
20
91
|
|
21
|
-
|
92
|
+
# @private
|
93
|
+
class EnsureExclusionOfMatcher < ValidationMatcher
|
94
|
+
def initialize(attribute)
|
95
|
+
super(attribute)
|
96
|
+
@array = nil
|
97
|
+
@range = nil
|
98
|
+
@expected_message = nil
|
99
|
+
end
|
100
|
+
|
22
101
|
def in_array(array)
|
23
102
|
@array = array
|
24
103
|
self
|