remarkable_activerecord 3.1.8 → 3.1.9
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.
- 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
|