remarkable_activerecord 3.1.8 → 3.1.9
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +140 -138
- data/LICENSE +20 -20
- data/README +80 -80
- data/lib/remarkable_activerecord.rb +29 -29
- data/lib/remarkable_activerecord/base.rb +248 -237
- data/lib/remarkable_activerecord/describe.rb +27 -27
- data/lib/remarkable_activerecord/human_names.rb +36 -36
- data/lib/remarkable_activerecord/matchers/accept_nested_attributes_for_matcher.rb +30 -30
- data/lib/remarkable_activerecord/matchers/allow_mass_assignment_of_matcher.rb +59 -59
- data/lib/remarkable_activerecord/matchers/allow_values_for_matcher.rb +85 -94
- data/lib/remarkable_activerecord/matchers/association_matcher.rb +283 -283
- data/lib/remarkable_activerecord/matchers/have_column_matcher.rb +68 -68
- data/lib/remarkable_activerecord/matchers/have_default_scope_matcher.rb +38 -38
- data/lib/remarkable_activerecord/matchers/have_index_matcher.rb +73 -73
- data/lib/remarkable_activerecord/matchers/have_readonly_attributes_matcher.rb +30 -30
- data/lib/remarkable_activerecord/matchers/have_scope_matcher.rb +85 -85
- data/lib/remarkable_activerecord/matchers/validate_acceptance_of_matcher.rb +50 -50
- data/lib/remarkable_activerecord/matchers/validate_associated_matcher.rb +97 -97
- data/lib/remarkable_activerecord/matchers/validate_confirmation_of_matcher.rb +44 -44
- data/lib/remarkable_activerecord/matchers/validate_exclusion_of_matcher.rb +53 -53
- data/lib/remarkable_activerecord/matchers/validate_inclusion_of_matcher.rb +52 -52
- data/lib/remarkable_activerecord/matchers/validate_length_of_matcher.rb +150 -150
- data/lib/remarkable_activerecord/matchers/validate_numericality_of_matcher.rb +181 -181
- data/lib/remarkable_activerecord/matchers/validate_presence_of_matcher.rb +29 -29
- data/lib/remarkable_activerecord/matchers/validate_uniqueness_of_matcher.rb +233 -233
- data/locale/en.yml +261 -261
- data/spec/accept_nested_attributes_for_matcher_spec.rb +1 -1
- data/spec/allow_mass_assignment_of_matcher_spec.rb +90 -82
- data/spec/allow_values_for_matcher_spec.rb +72 -63
- data/spec/association_matcher_spec.rb +612 -612
- data/spec/describe_spec.rb +3 -3
- data/spec/have_column_matcher_spec.rb +73 -73
- data/spec/have_default_scope_matcher_spec.rb +1 -1
- data/spec/have_index_matcher_spec.rb +87 -87
- data/spec/have_readonly_attributes_matcher_spec.rb +47 -47
- data/spec/have_scope_matcher_spec.rb +77 -77
- data/spec/model_builder.rb +101 -101
- data/spec/rcov.opts +1 -1
- data/spec/spec.opts +4 -4
- data/spec/spec_helper.rb +27 -27
- data/spec/validate_acceptance_of_matcher_spec.rb +68 -68
- data/spec/validate_associated_matcher_spec.rb +121 -121
- data/spec/validate_confirmation_of_matcher_spec.rb +58 -58
- data/spec/validate_length_of_matcher_spec.rb +218 -218
- data/spec/validate_numericality_of_matcher_spec.rb +179 -179
- data/spec/validate_presence_of_matcher_spec.rb +56 -56
- data/spec/validate_uniqueness_of_matcher_spec.rb +164 -164
- metadata +5 -5
@@ -1,57 +1,57 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'allow_values_for_matcher')
|
2
|
-
|
3
|
-
module Remarkable
|
4
|
-
module ActiveRecord
|
5
|
-
module Matchers
|
6
|
-
class ValidateInclusionOfMatcher < AllowValuesForMatcher #:nodoc:
|
1
|
+
require File.join(File.dirname(__FILE__), 'allow_values_for_matcher')
|
2
|
+
|
3
|
+
module Remarkable
|
4
|
+
module ActiveRecord
|
5
|
+
module Matchers
|
6
|
+
class ValidateInclusionOfMatcher < AllowValuesForMatcher #:nodoc:
|
7
7
|
# Don't allow it to behave in the negative way.
|
8
|
-
undef_method :does_not_match?
|
8
|
+
undef_method :does_not_match?
|
9
9
|
|
10
10
|
default_options :message => :inclusion
|
11
|
-
|
12
|
-
protected
|
13
|
-
|
14
|
-
def valid_values
|
15
|
-
@options[:in]
|
16
|
-
end
|
17
|
-
|
18
|
-
def invalid_values
|
19
|
-
if @in_range
|
20
|
-
[ @options[:in].first - 1, @options[:in].last + 1 ]
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def valid_values
|
15
|
+
@options[:in]
|
16
|
+
end
|
17
|
+
|
18
|
+
def invalid_values
|
19
|
+
if @in_range
|
20
|
+
[ @options[:in].first - 1, @options[:in].last + 1 ]
|
21
21
|
else
|
22
22
|
value = @options[:in].select{ |i| i.is_a?(String) }.max
|
23
|
-
value ? [ value.next ] : []
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
# Ensures that given values are valid for the attribute. If a range
|
30
|
-
# is given, ensures that the attribute is valid in the given range.
|
31
|
-
#
|
32
|
-
# If you give that :size accepts ["S", "M", "L"], it will test that "T"
|
33
|
-
# (the next of the array max value) is not allowed.
|
34
|
-
#
|
35
|
-
# == Options
|
36
|
-
#
|
37
|
-
# * <tt>:in</tt> - values to test inclusion.
|
38
|
-
# * <tt>:allow_nil</tt> - when supplied, validates if it allows nil or not.
|
39
|
-
# * <tt>:allow_blank</tt> - when supplied, validates if it allows blank or not.
|
40
|
-
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
41
|
-
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.inclusion')</tt>
|
42
|
-
#
|
43
|
-
# == Examples
|
44
|
-
#
|
45
|
-
# should_validate_inclusion_of :size, :in => ["S", "M", "L", "XL"]
|
46
|
-
# should_validate_inclusion_of :age, :in => 18..100
|
47
|
-
#
|
48
|
-
# it { should validate_inclusion_of(:size, :in => ["S", "M", "L", "XL"]) }
|
49
|
-
# it { should validate_inclusion_of(:age, :in => 18..100) }
|
50
|
-
#
|
51
|
-
def validate_inclusion_of(*args, &block)
|
52
|
-
ValidateInclusionOfMatcher.new(*args, &block).spec(self)
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
23
|
+
value ? [ value.next ] : []
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
# Ensures that given values are valid for the attribute. If a range
|
30
|
+
# is given, ensures that the attribute is valid in the given range.
|
31
|
+
#
|
32
|
+
# If you give that :size accepts ["S", "M", "L"], it will test that "T"
|
33
|
+
# (the next of the array max value) is not allowed.
|
34
|
+
#
|
35
|
+
# == Options
|
36
|
+
#
|
37
|
+
# * <tt>:in</tt> - values to test inclusion.
|
38
|
+
# * <tt>:allow_nil</tt> - when supplied, validates if it allows nil or not.
|
39
|
+
# * <tt>:allow_blank</tt> - when supplied, validates if it allows blank or not.
|
40
|
+
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
41
|
+
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.inclusion')</tt>
|
42
|
+
#
|
43
|
+
# == Examples
|
44
|
+
#
|
45
|
+
# should_validate_inclusion_of :size, :in => ["S", "M", "L", "XL"]
|
46
|
+
# should_validate_inclusion_of :age, :in => 18..100
|
47
|
+
#
|
48
|
+
# it { should validate_inclusion_of(:size, :in => ["S", "M", "L", "XL"]) }
|
49
|
+
# it { should validate_inclusion_of(:age, :in => 18..100) }
|
50
|
+
#
|
51
|
+
def validate_inclusion_of(*args, &block)
|
52
|
+
ValidateInclusionOfMatcher.new(*args, &block).spec(self)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -1,150 +1,150 @@
|
|
1
|
-
module Remarkable
|
2
|
-
module ActiveRecord
|
3
|
-
module Matchers
|
4
|
-
class ValidateLengthOfMatcher < Remarkable::ActiveRecord::Base #:nodoc:
|
5
|
-
arguments :collection => :attributes, :as => :attribute
|
6
|
-
|
7
|
-
optional :within, :alias => :in
|
8
|
-
optional :minimum, :maximum, :is
|
9
|
-
optional :token, :separator, :with_kind_of
|
10
|
-
optional :allow_nil, :allow_blank, :default => true
|
11
|
-
optional :message, :too_short, :too_long, :wrong_length
|
12
|
-
|
13
|
-
collection_assertions :less_than_min_length?, :exactly_min_length?,
|
14
|
-
:more_than_max_length?, :exactly_max_length?,
|
15
|
-
:allow_nil?, :allow_blank?
|
16
|
-
|
17
|
-
before_assert do
|
18
|
-
# Reassign :in to :within
|
19
|
-
@options[:within] ||= @options.delete(:in) if @options.key?(:in)
|
20
|
-
|
21
|
-
if @options[:is]
|
22
|
-
@min_value, @max_value = @options[:is], @options[:is]
|
23
|
-
elsif @options[:within]
|
24
|
-
@min_value, @max_value = @options[:within].first, @options[:within].last
|
25
|
-
elsif @options[:maximum]
|
26
|
-
@min_value, @max_value = nil, @options[:maximum]
|
27
|
-
elsif @options[:minimum]
|
28
|
-
@min_value, @max_value = @options[:minimum], nil
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
default_options :too_short => :too_short, :too_long => :too_long, :wrong_length => :wrong_length
|
33
|
-
|
34
|
-
protected
|
35
|
-
def allow_nil?
|
36
|
-
super(default_message_for(:too_short))
|
37
|
-
end
|
38
|
-
|
39
|
-
def allow_blank?
|
40
|
-
super(default_message_for(:too_short))
|
41
|
-
end
|
42
|
-
|
43
|
-
def less_than_min_length?
|
44
|
-
@min_value.nil? || @min_value <= 1 || bad?(value_for_length(@min_value - 1), default_message_for(:too_short))
|
45
|
-
end
|
46
|
-
|
47
|
-
def exactly_min_length?
|
48
|
-
@min_value.nil? || @min_value <= 0 || good?(value_for_length(@min_value), default_message_for(:too_short))
|
49
|
-
end
|
50
|
-
|
51
|
-
def more_than_max_length?
|
52
|
-
@max_value.nil? || bad?(value_for_length(@max_value + 1), default_message_for(:too_long))
|
53
|
-
end
|
54
|
-
|
55
|
-
def exactly_max_length?
|
56
|
-
@max_value.nil? || @min_value == @max_value || good?(value_for_length(@max_value), default_message_for(:too_long))
|
57
|
-
end
|
58
|
-
|
59
|
-
def value_for_length(value)
|
60
|
-
if @options[:with_kind_of]
|
61
|
-
[@options[:with_kind_of].new] * value
|
62
|
-
else
|
63
|
-
([@options.fetch(:token, 'x')] * value).join(@options.fetch(:separator, ''))
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def interpolation_options
|
68
|
-
{ :minimum => @min_value, :maximum => @max_value }
|
69
|
-
end
|
70
|
-
|
71
|
-
# Returns the default message for the validation type.
|
72
|
-
# If user supplied :message, it will return it. Otherwise it will return
|
73
|
-
# wrong_length on :is validation and :too_short or :too_long in the other
|
74
|
-
# types.
|
75
|
-
#
|
76
|
-
def default_message_for(validation_type)
|
77
|
-
return :message if @options[:message]
|
78
|
-
@options.key?(:is) ? :wrong_length : validation_type
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Validates the length of the given attributes. You have also to supply
|
83
|
-
# one of the following options: minimum, maximum, is or within.
|
84
|
-
#
|
85
|
-
# Note: this method is also aliased as <tt>validate_size_of</tt>.
|
86
|
-
#
|
87
|
-
# == Options
|
88
|
-
#
|
89
|
-
# * <tt>:minimum</tt> - The minimum size of the attribute.
|
90
|
-
# * <tt>:maximum</tt> - The maximum size of the attribute.
|
91
|
-
# * <tt>:is</tt> - The exact size of the attribute.
|
92
|
-
# * <tt>:within</tt> - A range specifying the minimum and maximum size of the attribute.
|
93
|
-
# * <tt>:in</tt> - A synonym(or alias) for :within.
|
94
|
-
# * <tt>:allow_nil</tt> - when supplied, validates if it allows nil or not.
|
95
|
-
# * <tt>:allow_blank</tt> - when supplied, validates if it allows blank or not.
|
96
|
-
# * <tt>:too_short</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt> when attribute is too short.
|
97
|
-
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.too_short') % range.first</tt>
|
98
|
-
# * <tt>:too_long</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt> when attribute is too long.
|
99
|
-
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.too_long') % range.last</tt>
|
100
|
-
# * <tt>:wrong_length</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt> when attribute is the wrong length.
|
101
|
-
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.wrong_length') % range.last</tt>
|
102
|
-
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
103
|
-
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.wrong_length') % value</tt>
|
104
|
-
#
|
105
|
-
# It also accepts an extra option called :with_kind_of. If you are validating
|
106
|
-
# the size of an association array, you have to specify the kind of the array
|
107
|
-
# being validated. For example, if your post accepts maximum 10 comments, you
|
108
|
-
# can do:
|
109
|
-
#
|
110
|
-
# should_validate_length_of :comments, :maximum => 10, :with_kind_of => Comment
|
111
|
-
#
|
112
|
-
# Finally, it also accepts :token and :separator, to specify how the
|
113
|
-
# tokenizer should work. For example, if you are splitting the attribute
|
114
|
-
# per word:
|
115
|
-
#
|
116
|
-
# validates_length_of :essay, :minimum => 100, :tokenizer => lambda {|str| str.scan(/\w+/) }
|
117
|
-
#
|
118
|
-
# You could do this:
|
119
|
-
#
|
120
|
-
# should_validate_length_of :essay, :minimum => 100, :token => "word", :separator => " "
|
121
|
-
#
|
122
|
-
# == Gotcha
|
123
|
-
#
|
124
|
-
# In Rails 2.3.x, when :message is supplied, it overwrites the messages
|
125
|
-
# supplied in :wrong_length, :too_short and :too_long. However, in earlier
|
126
|
-
# versions, Rails ignores the :message option.
|
127
|
-
#
|
128
|
-
# == Examples
|
129
|
-
#
|
130
|
-
# it { should validate_length_of(:password).within(6..20) }
|
131
|
-
# it { should validate_length_of(:password).maximum(20) }
|
132
|
-
# it { should validate_length_of(:password).minimum(6) }
|
133
|
-
# it { should validate_length_of(:age).is(18) }
|
134
|
-
#
|
135
|
-
# should_validate_length_of :password, :within => 6..20
|
136
|
-
# should_validate_length_of :password, :maximum => 20
|
137
|
-
# should_validate_length_of :password, :minimum => 6
|
138
|
-
# should_validate_length_of :age, :is => 18
|
139
|
-
#
|
140
|
-
# should_validate_length_of :password do |m|
|
141
|
-
# m.minimum 6
|
142
|
-
# m.maximum 20
|
143
|
-
# end
|
144
|
-
#
|
145
|
-
def validate_length_of(*attributes, &block)
|
146
|
-
ValidateLengthOfMatcher.new(*attributes, &block).spec(self)
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
1
|
+
module Remarkable
|
2
|
+
module ActiveRecord
|
3
|
+
module Matchers
|
4
|
+
class ValidateLengthOfMatcher < Remarkable::ActiveRecord::Base #:nodoc:
|
5
|
+
arguments :collection => :attributes, :as => :attribute
|
6
|
+
|
7
|
+
optional :within, :alias => :in
|
8
|
+
optional :minimum, :maximum, :is
|
9
|
+
optional :token, :separator, :with_kind_of
|
10
|
+
optional :allow_nil, :allow_blank, :default => true
|
11
|
+
optional :message, :too_short, :too_long, :wrong_length
|
12
|
+
|
13
|
+
collection_assertions :less_than_min_length?, :exactly_min_length?,
|
14
|
+
:more_than_max_length?, :exactly_max_length?,
|
15
|
+
:allow_nil?, :allow_blank?
|
16
|
+
|
17
|
+
before_assert do
|
18
|
+
# Reassign :in to :within
|
19
|
+
@options[:within] ||= @options.delete(:in) if @options.key?(:in)
|
20
|
+
|
21
|
+
if @options[:is]
|
22
|
+
@min_value, @max_value = @options[:is], @options[:is]
|
23
|
+
elsif @options[:within]
|
24
|
+
@min_value, @max_value = @options[:within].first, @options[:within].last
|
25
|
+
elsif @options[:maximum]
|
26
|
+
@min_value, @max_value = nil, @options[:maximum]
|
27
|
+
elsif @options[:minimum]
|
28
|
+
@min_value, @max_value = @options[:minimum], nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
default_options :too_short => :too_short, :too_long => :too_long, :wrong_length => :wrong_length
|
33
|
+
|
34
|
+
protected
|
35
|
+
def allow_nil?
|
36
|
+
super(default_message_for(:too_short))
|
37
|
+
end
|
38
|
+
|
39
|
+
def allow_blank?
|
40
|
+
super(default_message_for(:too_short))
|
41
|
+
end
|
42
|
+
|
43
|
+
def less_than_min_length?
|
44
|
+
@min_value.nil? || @min_value <= 1 || bad?(value_for_length(@min_value - 1), default_message_for(:too_short))
|
45
|
+
end
|
46
|
+
|
47
|
+
def exactly_min_length?
|
48
|
+
@min_value.nil? || @min_value <= 0 || good?(value_for_length(@min_value), default_message_for(:too_short))
|
49
|
+
end
|
50
|
+
|
51
|
+
def more_than_max_length?
|
52
|
+
@max_value.nil? || bad?(value_for_length(@max_value + 1), default_message_for(:too_long))
|
53
|
+
end
|
54
|
+
|
55
|
+
def exactly_max_length?
|
56
|
+
@max_value.nil? || @min_value == @max_value || good?(value_for_length(@max_value), default_message_for(:too_long))
|
57
|
+
end
|
58
|
+
|
59
|
+
def value_for_length(value)
|
60
|
+
if @options[:with_kind_of]
|
61
|
+
[@options[:with_kind_of].new] * value
|
62
|
+
else
|
63
|
+
([@options.fetch(:token, 'x')] * value).join(@options.fetch(:separator, ''))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def interpolation_options
|
68
|
+
{ :minimum => @min_value, :maximum => @max_value }
|
69
|
+
end
|
70
|
+
|
71
|
+
# Returns the default message for the validation type.
|
72
|
+
# If user supplied :message, it will return it. Otherwise it will return
|
73
|
+
# wrong_length on :is validation and :too_short or :too_long in the other
|
74
|
+
# types.
|
75
|
+
#
|
76
|
+
def default_message_for(validation_type)
|
77
|
+
return :message if @options[:message]
|
78
|
+
@options.key?(:is) ? :wrong_length : validation_type
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Validates the length of the given attributes. You have also to supply
|
83
|
+
# one of the following options: minimum, maximum, is or within.
|
84
|
+
#
|
85
|
+
# Note: this method is also aliased as <tt>validate_size_of</tt>.
|
86
|
+
#
|
87
|
+
# == Options
|
88
|
+
#
|
89
|
+
# * <tt>:minimum</tt> - The minimum size of the attribute.
|
90
|
+
# * <tt>:maximum</tt> - The maximum size of the attribute.
|
91
|
+
# * <tt>:is</tt> - The exact size of the attribute.
|
92
|
+
# * <tt>:within</tt> - A range specifying the minimum and maximum size of the attribute.
|
93
|
+
# * <tt>:in</tt> - A synonym(or alias) for :within.
|
94
|
+
# * <tt>:allow_nil</tt> - when supplied, validates if it allows nil or not.
|
95
|
+
# * <tt>:allow_blank</tt> - when supplied, validates if it allows blank or not.
|
96
|
+
# * <tt>:too_short</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt> when attribute is too short.
|
97
|
+
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.too_short') % range.first</tt>
|
98
|
+
# * <tt>:too_long</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt> when attribute is too long.
|
99
|
+
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.too_long') % range.last</tt>
|
100
|
+
# * <tt>:wrong_length</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt> when attribute is the wrong length.
|
101
|
+
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.wrong_length') % range.last</tt>
|
102
|
+
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
103
|
+
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.wrong_length') % value</tt>
|
104
|
+
#
|
105
|
+
# It also accepts an extra option called :with_kind_of. If you are validating
|
106
|
+
# the size of an association array, you have to specify the kind of the array
|
107
|
+
# being validated. For example, if your post accepts maximum 10 comments, you
|
108
|
+
# can do:
|
109
|
+
#
|
110
|
+
# should_validate_length_of :comments, :maximum => 10, :with_kind_of => Comment
|
111
|
+
#
|
112
|
+
# Finally, it also accepts :token and :separator, to specify how the
|
113
|
+
# tokenizer should work. For example, if you are splitting the attribute
|
114
|
+
# per word:
|
115
|
+
#
|
116
|
+
# validates_length_of :essay, :minimum => 100, :tokenizer => lambda {|str| str.scan(/\w+/) }
|
117
|
+
#
|
118
|
+
# You could do this:
|
119
|
+
#
|
120
|
+
# should_validate_length_of :essay, :minimum => 100, :token => "word", :separator => " "
|
121
|
+
#
|
122
|
+
# == Gotcha
|
123
|
+
#
|
124
|
+
# In Rails 2.3.x, when :message is supplied, it overwrites the messages
|
125
|
+
# supplied in :wrong_length, :too_short and :too_long. However, in earlier
|
126
|
+
# versions, Rails ignores the :message option.
|
127
|
+
#
|
128
|
+
# == Examples
|
129
|
+
#
|
130
|
+
# it { should validate_length_of(:password).within(6..20) }
|
131
|
+
# it { should validate_length_of(:password).maximum(20) }
|
132
|
+
# it { should validate_length_of(:password).minimum(6) }
|
133
|
+
# it { should validate_length_of(:age).is(18) }
|
134
|
+
#
|
135
|
+
# should_validate_length_of :password, :within => 6..20
|
136
|
+
# should_validate_length_of :password, :maximum => 20
|
137
|
+
# should_validate_length_of :password, :minimum => 6
|
138
|
+
# should_validate_length_of :age, :is => 18
|
139
|
+
#
|
140
|
+
# should_validate_length_of :password do |m|
|
141
|
+
# m.minimum 6
|
142
|
+
# m.maximum 20
|
143
|
+
# end
|
144
|
+
#
|
145
|
+
def validate_length_of(*attributes, &block)
|
146
|
+
ValidateLengthOfMatcher.new(*attributes, &block).spec(self)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -1,188 +1,188 @@
|
|
1
|
-
module Remarkable
|
2
|
-
module ActiveRecord
|
3
|
-
module Matchers
|
4
|
-
class ValidateNumericalityOfMatcher < Remarkable::ActiveRecord::Base #:nodoc:
|
5
|
-
arguments :collection => :attributes, :as => :attribute
|
6
|
-
|
7
|
-
optional :equal_to, :greater_than_or_equal_to, :greater_than,
|
8
|
-
:less_than_or_equal_to, :less_than, :message
|
9
|
-
|
10
|
-
optional :only_integer, :odd, :even, :allow_nil, :allow_blank, :default => true
|
11
|
-
|
12
|
-
collection_assertions :only_numeric_values?, :allow_blank?, :allow_nil?,
|
13
|
-
:only_integer?, :only_odd?, :only_even?, :equals_to?,
|
14
|
-
:less_than_minimum?, :more_than_maximum?
|
15
|
-
|
16
|
-
# Before assertions, we rearrange the values.
|
17
|
-
#
|
18
|
-
# Notice that :less_than gives a maximum value while :more_than given
|
19
|
-
# a minimum value. While :equal_to generate both.
|
20
|
-
#
|
21
|
-
before_assert do
|
22
|
-
@maximum_values = {}
|
23
|
-
@minimum_values = {}
|
24
|
-
|
25
|
-
if value = @options[:equal_to]
|
26
|
-
@maximum_values[:equal_to] = value
|
27
|
-
@minimum_values[:equal_to] = value
|
28
|
-
elsif value = @options[:less_than]
|
29
|
-
@maximum_values[:less_than] = value - 1
|
30
|
-
elsif value = @options[:greater_than]
|
31
|
-
@minimum_values[:greater_than] = value + 1
|
32
|
-
elsif value = @options[:less_than_or_equal_to]
|
33
|
-
@maximum_values[:less_than_or_equal_to] = value
|
34
|
-
elsif value = @options[:greater_than_or_equal_to]
|
35
|
-
@minimum_values[:greater_than_or_equal_to] = value
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def allow_nil?
|
42
|
-
super(default_message_for(:not_a_number))
|
43
|
-
end
|
44
|
-
|
45
|
-
def allow_blank?
|
46
|
-
super(default_message_for(:not_a_number))
|
47
|
-
end
|
48
|
-
|
49
|
-
def only_numeric_values?
|
50
|
-
bad?("abcd", default_message_for(:not_a_number))
|
51
|
-
end
|
52
|
-
|
53
|
-
def only_integer?
|
54
|
-
assert_bad_or_good_if_key(:only_integer, valid_value_for_test.to_f, default_message_for(:not_a_number))
|
55
|
-
end
|
56
|
-
|
57
|
-
# In ActiveRecord, when we supply :even, does not matter the value, it
|
58
|
-
# considers that should even values should be accepted.
|
59
|
-
#
|
60
|
-
def only_even?
|
61
|
-
return true unless @options[:even]
|
62
|
-
bad?(even_valid_value_for_test + 1, default_message_for(:even))
|
63
|
-
end
|
64
|
-
|
65
|
-
# In ActiveRecord, when we supply :odd, does not matter the value, it
|
66
|
-
# considers that should odd values should be accepted.
|
67
|
-
#
|
68
|
-
def only_odd?
|
69
|
-
return true unless @options[:odd]
|
70
|
-
bad?(even_valid_value_for_test, default_message_for(:odd))
|
71
|
-
end
|
72
|
-
|
73
|
-
# Check equal_to for all registered values.
|
74
|
-
#
|
75
|
-
def equals_to?
|
76
|
-
values = {}
|
77
|
-
@maximum_values.each { |k, v| values[k] = v }
|
78
|
-
@minimum_values.each { |k, v| values[k] = v }
|
79
|
-
|
80
|
-
values.each do |key, value|
|
81
|
-
return false, :count => value unless good?(value, default_message_for(key))
|
82
|
-
end
|
83
|
-
true
|
84
|
-
end
|
85
|
-
|
86
|
-
# Check more_than_maximum? for equal_to, less_than and
|
87
|
-
# less_than_or_equal_to options.
|
88
|
-
#
|
89
|
-
def more_than_maximum?
|
90
|
-
@maximum_values.each do |key, value|
|
91
|
-
return false, :count => value unless bad?(value + 1, default_message_for(key))
|
92
|
-
end
|
93
|
-
true
|
94
|
-
end
|
95
|
-
|
96
|
-
# Check less_than_minimum? for equal_to, more_than and
|
97
|
-
# more_than_or_equal_to options.
|
98
|
-
#
|
99
|
-
def less_than_minimum?
|
100
|
-
@minimum_values.each do |key, value|
|
101
|
-
return false, :count => value unless bad?(value - 1, default_message_for(key))
|
102
|
-
end
|
103
|
-
true
|
104
|
-
end
|
105
|
-
|
106
|
-
# Returns a valid value for test.
|
107
|
-
#
|
108
|
-
def valid_value_for_test
|
109
|
-
value = @options[:equal_to] || @options[:less_than_or_equal_to] || @options[:greater_than_or_equal_to]
|
110
|
-
|
111
|
-
value ||= @options[:less_than] - 1 if @options[:less_than]
|
112
|
-
value ||= @options[:greater_than] + 1 if @options[:greater_than]
|
113
|
-
|
114
|
-
value ||= 10
|
115
|
-
|
116
|
-
if @options[:even]
|
117
|
-
value = (value / 2) * 2
|
118
|
-
elsif @options[:odd]
|
119
|
-
value = ((value / 2) * 2) + 1
|
120
|
-
end
|
121
|
-
|
122
|
-
value
|
123
|
-
end
|
124
|
-
|
125
|
-
# Returns a valid even value for test.
|
126
|
-
# The method valid_value_for_test checks for :even option but does not
|
127
|
-
# return necessarily an even value
|
128
|
-
#
|
129
|
-
def even_valid_value_for_test
|
130
|
-
(valid_value_for_test / 2) * 2
|
131
|
-
end
|
132
|
-
|
133
|
-
# Returns the default message for each key (:odd, :even, :equal_to, ...).
|
134
|
-
# If the user provided a message, we use it, otherwise we should use
|
135
|
-
# the given key as message.
|
136
|
-
#
|
137
|
-
# For example, a default_message_for(:odd), if none is provided, will be
|
138
|
-
# :odd. So we have create :odd_message in the options hash, that when
|
139
|
-
# called later, will return :odd.
|
140
|
-
#
|
141
|
-
def default_message_for(key)
|
142
|
-
if @options[:message]
|
143
|
-
:message
|
144
|
-
else
|
145
|
-
@options[:"#{key}_message"] = key
|
146
|
-
:"#{key}_message"
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
# Ensures that the given attributes accepts only numbers.
|
152
|
-
#
|
153
|
-
# == Options
|
154
|
-
#
|
155
|
-
# * <tt>:only_integer</tt> - when supplied, checks if it accepts only integers or not
|
156
|
-
# * <tt>:odd</tt> - when supplied, checks if it accepts only odd values or not
|
157
|
-
# * <tt>:even</tt> - when supplied, checks if it accepts only even values or not
|
158
|
-
# * <tt>:equal_to</tt> - when supplied, checks if attributes are only valid when equal to given value
|
159
|
-
# * <tt>:less_than</tt> - when supplied, checks if attributes are only valid when less than given value
|
160
|
-
# * <tt>:greater_than</tt> - when supplied, checks if attributes are only valid when greater than given value
|
161
|
-
# * <tt>:less_than_or_equal_to</tt> - when supplied, checks if attributes are only valid when less than or equal to given value
|
162
|
-
# * <tt>:greater_than_or_equal_to</tt> - when supplied, checks if attributes are only valid when greater than or equal to given value
|
163
|
-
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
164
|
-
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.not_a_number')</tt>
|
165
|
-
#
|
166
|
-
# == Examples
|
167
|
-
#
|
168
|
-
# it { should validate_numericality_of(:age).odd }
|
169
|
-
# it { should validate_numericality_of(:age).even }
|
170
|
-
# it { should validate_numericality_of(:age).only_integer }
|
171
|
-
# it { should validate_numericality_of(:age, :odd => true) }
|
172
|
-
# it { should validate_numericality_of(:age, :even => true) }
|
1
|
+
module Remarkable
|
2
|
+
module ActiveRecord
|
3
|
+
module Matchers
|
4
|
+
class ValidateNumericalityOfMatcher < Remarkable::ActiveRecord::Base #:nodoc:
|
5
|
+
arguments :collection => :attributes, :as => :attribute
|
6
|
+
|
7
|
+
optional :equal_to, :greater_than_or_equal_to, :greater_than,
|
8
|
+
:less_than_or_equal_to, :less_than, :message
|
9
|
+
|
10
|
+
optional :only_integer, :odd, :even, :allow_nil, :allow_blank, :default => true
|
11
|
+
|
12
|
+
collection_assertions :only_numeric_values?, :allow_blank?, :allow_nil?,
|
13
|
+
:only_integer?, :only_odd?, :only_even?, :equals_to?,
|
14
|
+
:less_than_minimum?, :more_than_maximum?
|
15
|
+
|
16
|
+
# Before assertions, we rearrange the values.
|
17
|
+
#
|
18
|
+
# Notice that :less_than gives a maximum value while :more_than given
|
19
|
+
# a minimum value. While :equal_to generate both.
|
20
|
+
#
|
21
|
+
before_assert do
|
22
|
+
@maximum_values = {}
|
23
|
+
@minimum_values = {}
|
24
|
+
|
25
|
+
if value = @options[:equal_to]
|
26
|
+
@maximum_values[:equal_to] = value
|
27
|
+
@minimum_values[:equal_to] = value
|
28
|
+
elsif value = @options[:less_than]
|
29
|
+
@maximum_values[:less_than] = value - 1
|
30
|
+
elsif value = @options[:greater_than]
|
31
|
+
@minimum_values[:greater_than] = value + 1
|
32
|
+
elsif value = @options[:less_than_or_equal_to]
|
33
|
+
@maximum_values[:less_than_or_equal_to] = value
|
34
|
+
elsif value = @options[:greater_than_or_equal_to]
|
35
|
+
@minimum_values[:greater_than_or_equal_to] = value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def allow_nil?
|
42
|
+
super(default_message_for(:not_a_number))
|
43
|
+
end
|
44
|
+
|
45
|
+
def allow_blank?
|
46
|
+
super(default_message_for(:not_a_number))
|
47
|
+
end
|
48
|
+
|
49
|
+
def only_numeric_values?
|
50
|
+
bad?("abcd", default_message_for(:not_a_number))
|
51
|
+
end
|
52
|
+
|
53
|
+
def only_integer?
|
54
|
+
assert_bad_or_good_if_key(:only_integer, valid_value_for_test.to_f, default_message_for(:not_a_number))
|
55
|
+
end
|
56
|
+
|
57
|
+
# In ActiveRecord, when we supply :even, does not matter the value, it
|
58
|
+
# considers that should even values should be accepted.
|
59
|
+
#
|
60
|
+
def only_even?
|
61
|
+
return true unless @options[:even]
|
62
|
+
bad?(even_valid_value_for_test + 1, default_message_for(:even))
|
63
|
+
end
|
64
|
+
|
65
|
+
# In ActiveRecord, when we supply :odd, does not matter the value, it
|
66
|
+
# considers that should odd values should be accepted.
|
67
|
+
#
|
68
|
+
def only_odd?
|
69
|
+
return true unless @options[:odd]
|
70
|
+
bad?(even_valid_value_for_test, default_message_for(:odd))
|
71
|
+
end
|
72
|
+
|
73
|
+
# Check equal_to for all registered values.
|
74
|
+
#
|
75
|
+
def equals_to?
|
76
|
+
values = {}
|
77
|
+
@maximum_values.each { |k, v| values[k] = v }
|
78
|
+
@minimum_values.each { |k, v| values[k] = v }
|
79
|
+
|
80
|
+
values.each do |key, value|
|
81
|
+
return false, :count => value unless good?(value, default_message_for(key))
|
82
|
+
end
|
83
|
+
true
|
84
|
+
end
|
85
|
+
|
86
|
+
# Check more_than_maximum? for equal_to, less_than and
|
87
|
+
# less_than_or_equal_to options.
|
88
|
+
#
|
89
|
+
def more_than_maximum?
|
90
|
+
@maximum_values.each do |key, value|
|
91
|
+
return false, :count => value unless bad?(value + 1, default_message_for(key))
|
92
|
+
end
|
93
|
+
true
|
94
|
+
end
|
95
|
+
|
96
|
+
# Check less_than_minimum? for equal_to, more_than and
|
97
|
+
# more_than_or_equal_to options.
|
98
|
+
#
|
99
|
+
def less_than_minimum?
|
100
|
+
@minimum_values.each do |key, value|
|
101
|
+
return false, :count => value unless bad?(value - 1, default_message_for(key))
|
102
|
+
end
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
# Returns a valid value for test.
|
107
|
+
#
|
108
|
+
def valid_value_for_test
|
109
|
+
value = @options[:equal_to] || @options[:less_than_or_equal_to] || @options[:greater_than_or_equal_to]
|
110
|
+
|
111
|
+
value ||= @options[:less_than] - 1 if @options[:less_than]
|
112
|
+
value ||= @options[:greater_than] + 1 if @options[:greater_than]
|
113
|
+
|
114
|
+
value ||= 10
|
115
|
+
|
116
|
+
if @options[:even]
|
117
|
+
value = (value / 2) * 2
|
118
|
+
elsif @options[:odd]
|
119
|
+
value = ((value / 2) * 2) + 1
|
120
|
+
end
|
121
|
+
|
122
|
+
value
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns a valid even value for test.
|
126
|
+
# The method valid_value_for_test checks for :even option but does not
|
127
|
+
# return necessarily an even value
|
128
|
+
#
|
129
|
+
def even_valid_value_for_test
|
130
|
+
(valid_value_for_test / 2) * 2
|
131
|
+
end
|
132
|
+
|
133
|
+
# Returns the default message for each key (:odd, :even, :equal_to, ...).
|
134
|
+
# If the user provided a message, we use it, otherwise we should use
|
135
|
+
# the given key as message.
|
136
|
+
#
|
137
|
+
# For example, a default_message_for(:odd), if none is provided, will be
|
138
|
+
# :odd. So we have create :odd_message in the options hash, that when
|
139
|
+
# called later, will return :odd.
|
140
|
+
#
|
141
|
+
def default_message_for(key)
|
142
|
+
if @options[:message]
|
143
|
+
:message
|
144
|
+
else
|
145
|
+
@options[:"#{key}_message"] = key
|
146
|
+
:"#{key}_message"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Ensures that the given attributes accepts only numbers.
|
173
152
|
#
|
174
|
-
#
|
153
|
+
# == Options
|
154
|
+
#
|
155
|
+
# * <tt>:only_integer</tt> - when supplied, checks if it accepts only integers or not
|
156
|
+
# * <tt>:odd</tt> - when supplied, checks if it accepts only odd values or not
|
157
|
+
# * <tt>:even</tt> - when supplied, checks if it accepts only even values or not
|
158
|
+
# * <tt>:equal_to</tt> - when supplied, checks if attributes are only valid when equal to given value
|
159
|
+
# * <tt>:less_than</tt> - when supplied, checks if attributes are only valid when less than given value
|
160
|
+
# * <tt>:greater_than</tt> - when supplied, checks if attributes are only valid when greater than given value
|
161
|
+
# * <tt>:less_than_or_equal_to</tt> - when supplied, checks if attributes are only valid when less than or equal to given value
|
162
|
+
# * <tt>:greater_than_or_equal_to</tt> - when supplied, checks if attributes are only valid when greater than or equal to given value
|
163
|
+
# * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
|
164
|
+
# Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.not_a_number')</tt>
|
165
|
+
#
|
166
|
+
# == Examples
|
167
|
+
#
|
168
|
+
# it { should validate_numericality_of(:age).odd }
|
169
|
+
# it { should validate_numericality_of(:age).even }
|
170
|
+
# it { should validate_numericality_of(:age).only_integer }
|
171
|
+
# it { should validate_numericality_of(:age, :odd => true) }
|
172
|
+
# it { should validate_numericality_of(:age, :even => true) }
|
173
|
+
#
|
174
|
+
# should_validate_numericality_of :age, :price
|
175
175
|
# should_validate_numericality_of :price, :only_integer => false, :greater_than => 10
|
176
176
|
#
|
177
177
|
# should_validate_numericality_of :price do |m|
|
178
178
|
# m.only_integer = false
|
179
179
|
# m.greater_than = 10
|
180
180
|
# end
|
181
|
-
#
|
182
|
-
def validate_numericality_of(*attributes, &block)
|
183
|
-
ValidateNumericalityOfMatcher.new(*attributes, &block).spec(self)
|
184
|
-
end
|
185
|
-
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
181
|
+
#
|
182
|
+
def validate_numericality_of(*attributes, &block)
|
183
|
+
ValidateNumericalityOfMatcher.new(*attributes, &block).spec(self)
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|