remarkable_activemodel 4.0.0.alpha1

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.
@@ -0,0 +1,188 @@
1
+ module Remarkable
2
+ module ActiveModel
3
+ module Matchers
4
+ class ValidateNumericalityOfMatcher < Remarkable::ActiveModel::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 ActiveModel, 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 ActiveModel, 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[: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
+ # should_validate_numericality_of :price, :only_integer => false, :greater_than => 10
176
+ #
177
+ # should_validate_numericality_of :price do |m|
178
+ # m.only_integer = false
179
+ # m.greater_than = 10
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
@@ -0,0 +1,91 @@
1
+ module Remarkable
2
+ module ActiveModel
3
+ # Holds ActiveModel matchers.
4
+ #
5
+ # == Validations matchers
6
+ #
7
+ # Remarkable supports all ActiveModel validations, and the only options
8
+ # not supported in those matchers is the :on options. So whenever you have
9
+ # to test that a validation runs on update, you have to do reproduce the
10
+ # state in your tests:
11
+ #
12
+ # describe Project do
13
+ # describe 'validations on create' do
14
+ # should_validate_presence_of :title
15
+ # end
16
+ #
17
+ # describe 'validations on update' do
18
+ # subject { Post.create!(@valid_attributes) }
19
+ # should_validate_presence_of :updated_at
20
+ # end
21
+ # end
22
+ #
23
+ # Another behavior in validations is the :message option. Whenever you change
24
+ # the message in your model, it must be given in your tests too:
25
+ #
26
+ # class Post < ActiveModel::Base
27
+ # validates_presence_of :title, :message => 'must be filled'
28
+ # end
29
+ #
30
+ # describe Post do
31
+ # should_validate_presence_of :title #=> fails
32
+ # should_validate_presence_of :title, :message => 'must be filled'
33
+ # end
34
+ #
35
+ # However, if you change the title using the I18n API, you don't need to
36
+ # specify the message in your tests, because it's retrieved properly.
37
+ #
38
+ module Matchers
39
+ class ValidatePresenceOfMatcher < Remarkable::ActiveModel::Base #:nodoc:
40
+ arguments :collection => :attributes, :as => :attribute
41
+ optional :message
42
+
43
+ collection_assertions :allow_nil?
44
+ default_options :message => :blank
45
+
46
+ protected
47
+
48
+ def allow_nil?
49
+ bad?(blank_value, :message)
50
+ end
51
+
52
+ def blank_value
53
+ collection? ? [] : nil
54
+ end
55
+
56
+ def collection?
57
+ if reflection = find_reflection
58
+ [:has_many, :has_and_belongs_to_many].include?(reflection.macro)
59
+ else
60
+ false
61
+ end
62
+ end
63
+
64
+ private
65
+
66
+ def find_reflection
67
+ if subject_class.respond_to?(:reflect_on_association)
68
+ subject_class.reflect_on_association(@attribute)
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ # Ensures that the model cannot be saved if one of the attributes listed is not present.
75
+ #
76
+ # == Options
77
+ #
78
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors[:attribute]</tt>.
79
+ # Regexp, string or symbol. Default = <tt>I18n.translate('activerecord.errors.messages.blank')</tt>
80
+ #
81
+ # == Examples
82
+ #
83
+ # should_validate_presence_of :name, :phone_number
84
+ # it { should validate_presence_of(:name, :phone_number) }
85
+ #
86
+ def validate_presence_of(*args, &block)
87
+ ValidatePresenceOfMatcher.new(*args, &block).spec(self)
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,116 @@
1
+ en:
2
+ remarkable:
3
+ active_model:
4
+ describe:
5
+ each: "{{key}} is {{value}}"
6
+ prepend: "when "
7
+ connector: " and "
8
+ expectations:
9
+ allow_nil: "{{subject_name}} to {{not}}allow nil values for {{attribute}}"
10
+ allow_blank: "{{subject_name}} to {{not}}allow blank values for {{attribute}}"
11
+ optionals:
12
+ allow_nil:
13
+ positive: "allowing nil values"
14
+ negative: "not allowing nil values"
15
+ allow_blank:
16
+ positive: "allowing blank values"
17
+ negative: "not allowing blank values"
18
+
19
+ allow_values_for:
20
+ description: "allow {{in}} as values for {{attributes}}"
21
+ expectations:
22
+ is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
23
+
24
+ validate_acceptance_of:
25
+ description: "require {{attributes}} to be accepted"
26
+ expectations:
27
+ requires_acceptance: "{{subject_name}} to be invalid if {{attribute}} is not accepted"
28
+ accept_is_valid: "{{subject_name}} to be valid when {{attribute}} is accepted with value {{accept}}"
29
+ optionals:
30
+ accept:
31
+ positive: "with value {{inspect}}"
32
+
33
+ validate_confirmation_of:
34
+ description: "require {{attributes}} to be confirmed"
35
+ expectations:
36
+ responds_to_confirmation: "{{subject_name}} instance responds to {{attribute}}_confirmation"
37
+ confirms: "{{subject_name}} to be valid only when {{attribute}} is confirmed"
38
+
39
+ validate_exclusion_of:
40
+ description: "ensure exclusion of {{attributes}} in {{in}}"
41
+ expectations:
42
+ is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
43
+ is_invalid: "{{subject_name}} to be invalid when {{attribute}} is set to {{value}}"
44
+
45
+ validate_inclusion_of:
46
+ description: "ensure inclusion of {{attributes}} in {{in}}"
47
+ expectations:
48
+ is_valid: "{{subject_name}} to be valid when {{attribute}} is set to {{value}}"
49
+ is_invalid: "{{subject_name}} to be invalid when {{attribute}} is set to {{value}}"
50
+
51
+ validate_length_of:
52
+ description: "ensure length of {{attributes}}"
53
+ expectations:
54
+ less_than_min_length: "{{subject_name}} to be invalid when {{attribute}} length is less than {{minimum}} characters"
55
+ exactly_min_length: "{{subject_name}} to be valid when {{attribute}} length is {{minimum}} characters"
56
+ more_than_max_length: "{{subject_name}} to be invalid when {{attribute}} length is more than {{maximum}} characters"
57
+ exactly_max_length: "{{subject_name}} to be valid when {{attribute}} length is {{maximum}} characters"
58
+ optionals:
59
+ within:
60
+ positive: "is within {{inspect}} characters"
61
+ maximum:
62
+ positive: "is maximum {{inspect}} characters"
63
+ minimum:
64
+ positive: "is minimum {{inspect}} characters"
65
+ is:
66
+ positive: "is equal to {{inspect}} characters"
67
+ with_kind_of:
68
+ positive: "with kind of {{value}}"
69
+
70
+ validate_numericality_of:
71
+ description: "ensure numericality of {{attributes}}"
72
+ expectations:
73
+ only_numeric_values: "{{subject_name}} to allow only numeric values for {{attribute}}"
74
+ only_integer: "{{subject_name}} to {{not}}allow only integer values for {{attribute}}"
75
+ only_even: "{{subject_name}} to allow only even values for {{attribute}}"
76
+ only_odd: "{{subject_name}} to allow only odd values for {{attribute}}"
77
+ equals_to: "{{subject_name}} to be valid only when {{attribute}} is equal to {{count}}"
78
+ more_than_maximum: "{{subject_name}} to be invalid when {{attribute}} is greater than {{count}}"
79
+ less_than_minimum: "{{subject_name}} to be invalid when {{attribute}} is less than {{count}}"
80
+ optionals:
81
+ only_integer:
82
+ positive: "allowing only integer values"
83
+ odd:
84
+ positive: "allowing only odd values"
85
+ even:
86
+ positive: "allowing only even values"
87
+ equal_to:
88
+ positive: "is equal to {{inspect}}"
89
+ less_than:
90
+ positive: "is less than {{inspect}}"
91
+ greater_than:
92
+ positive: "is greater than {{inspect}}"
93
+ less_than_or_equal_to:
94
+ positive: "is less than or equal to {{inspect}}"
95
+ greater_than_or_equal_to:
96
+ positive: "is greater than or equal to {{inspect}}"
97
+
98
+ validate_presence_of:
99
+ description: "require {{attributes}} to be set"
100
+ expectations:
101
+ allow_nil: "{{subject_name}} to require {{attribute}} to be set"
102
+
103
+ validate_uniqueness_of:
104
+ description: "require unique values for {{attributes}}"
105
+ expectations:
106
+ responds_to_scope: "{{subject_name}} instance responds to {{method}}"
107
+ is_unique: "{{subject_name}} to require unique values for {{attribute}}"
108
+ case_sensitive: "{{subject_name}} to {{not}}be case sensitive on {{attribute}} validation"
109
+ valid_with_new_scope: "{{subject_name}} to be valid when {{attribute}} scope ({{method}}) change"
110
+ optionals:
111
+ scope:
112
+ positive: "scoped to {{sentence}}"
113
+ case_sensitive:
114
+ positive: "case sensitive"
115
+ negative: "case insensitive"
116
+
@@ -0,0 +1,61 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{remarkable_activemodel}
8
+ s.version = "4.0.0.alpha1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ho-Sheng Hsiao", "Carlos Brando", "Jos\303\251 Valim", "Diego Carrion"]
12
+ s.date = %q{2010-04-22}
13
+ s.description = %q{Remarkable ActiveModel: collection of matchers and macros with I18n for ActiveModel}
14
+ s.email = ["hosh@sparkfly.com", "eduardobrando@gmail.com", "jose.valim@gmail.com", "dc.rec1@gmail.com"]
15
+ s.extra_rdoc_files = [
16
+ "CHANGELOG",
17
+ "LICENSE",
18
+ "README"
19
+ ]
20
+ s.files = [
21
+ "CHANGELOG",
22
+ "LICENSE",
23
+ "README",
24
+ "lib/remarkable_activemodel.rb",
25
+ "lib/remarkable_activemodel/base.rb",
26
+ "lib/remarkable_activemodel/matchers/allow_values_for_matcher.rb",
27
+ "lib/remarkable_activemodel/matchers/validate_acceptance_of_matcher.rb",
28
+ "lib/remarkable_activemodel/matchers/validate_confirmation_of_matcher.rb",
29
+ "lib/remarkable_activemodel/matchers/validate_exclusion_of_matcher.rb",
30
+ "lib/remarkable_activemodel/matchers/validate_inclusion_of_matcher.rb",
31
+ "lib/remarkable_activemodel/matchers/validate_length_of_matcher.rb",
32
+ "lib/remarkable_activemodel/matchers/validate_numericality_of_matcher.rb",
33
+ "lib/remarkable_activemodel/matchers/validate_presence_of_matcher.rb",
34
+ "locale/en.yml",
35
+ "remarkable_activemodel.gemspec",
36
+ "remarkable_activerecord.gemspec"
37
+ ]
38
+ s.homepage = %q{http://github.com/carlosbrando/remarkable}
39
+ s.rdoc_options = ["--charset=UTF-8"]
40
+ s.require_paths = ["lib"]
41
+ s.rubyforge_project = %q{remarkable}
42
+ s.rubygems_version = %q{1.3.6}
43
+ s.summary = %q{Remarkable ActiveModel: collection of matchers and macros with I18n for ActiveModel}
44
+
45
+ if s.respond_to? :specification_version then
46
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
47
+ s.specification_version = 3
48
+
49
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
50
+ s.add_runtime_dependency(%q<rspec>, [">= 2.0.0.alpha7"])
51
+ s.add_runtime_dependency(%q<remarkable>, ["~> 4.0.0.alpha1"])
52
+ else
53
+ s.add_dependency(%q<rspec>, [">= 2.0.0.alpha7"])
54
+ s.add_dependency(%q<remarkable>, ["~> 4.0.0.alpha1"])
55
+ end
56
+ else
57
+ s.add_dependency(%q<rspec>, [">= 2.0.0.alpha7"])
58
+ s.add_dependency(%q<remarkable>, ["~> 4.0.0.alpha1"])
59
+ end
60
+ end
61
+