shoulda-matchers 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +8 -8
- data/.travis.yml +9 -15
- data/Appraisals +10 -8
- data/Gemfile.lock +1 -1
- data/NEWS.md +62 -32
- data/gemfiles/3.0.gemfile.lock +2 -2
- data/gemfiles/3.1.gemfile.lock +2 -2
- data/gemfiles/3.2.gemfile +1 -1
- data/gemfiles/3.2.gemfile.lock +3 -3
- data/lib/shoulda/matchers/active_model.rb +1 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +7 -2
- data/lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +2 -0
- data/lib/shoulda/matchers/active_model/exception_message_finder.rb +3 -2
- data/lib/shoulda/matchers/active_model/helpers.rb +5 -2
- data/lib/shoulda/matchers/active_model/odd_even_number_matcher.rb +47 -0
- data/lib/shoulda/matchers/active_model/only_integer_matcher.rb +4 -0
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +26 -3
- data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +68 -16
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +5 -0
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +3 -2
- data/lib/shoulda/matchers/active_record/association_matcher.rb +29 -4
- data/lib/shoulda/matchers/version.rb +1 -1
- data/shoulda-matchers.gemspec +1 -0
- data/spec/shoulda/active_model/validate_uniqueness_of_matcher_spec.rb +195 -0
- data/spec/shoulda/matchers/active_model/allow_value_matcher_spec.rb +18 -0
- data/spec/shoulda/matchers/active_model/ensure_exclusion_of_matcher_spec.rb +21 -0
- data/spec/shoulda/matchers/active_model/ensure_inclusion_of_matcher_spec.rb +23 -0
- data/spec/shoulda/matchers/active_model/ensure_length_of_matcher_spec.rb +46 -0
- data/spec/shoulda/matchers/active_model/odd_even_number_matcher_spec.rb +93 -0
- data/spec/shoulda/matchers/active_model/only_integer_matcher_spec.rb +4 -4
- data/spec/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +60 -0
- data/spec/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +16 -0
- data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +45 -8
- data/spec/shoulda/matchers/active_model/validation_message_finder_spec.rb +13 -0
- data/spec/shoulda/matchers/active_record/association_matcher_spec.rb +50 -2
- data/spec/support/i18n_faker.rb +10 -0
- metadata +10 -3
@@ -8,10 +8,14 @@ module Shoulda # :nodoc:
|
|
8
8
|
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
|
9
9
|
# translation for <tt>:not_a_number</tt>.
|
10
10
|
# * <tt>only_integer</tt> - allows only integer values
|
11
|
+
# * <tt>odd</tt> - Specifies the value must be an odd number.
|
12
|
+
# * <tt>even</tt> - Specifies the value must be an even number.
|
11
13
|
#
|
12
14
|
# Examples:
|
13
15
|
# it { should validate_numericality_of(:price) }
|
14
16
|
# it { should validate_numericality_of(:age).only_integer }
|
17
|
+
# it { should validate_numericality_of(:frequency).odd }
|
18
|
+
# it { should validate_numericality_of(:frequency).even }
|
15
19
|
#
|
16
20
|
def validate_numericality_of(attr)
|
17
21
|
ValidateNumericalityOfMatcher.new(attr)
|
@@ -22,7 +26,6 @@ module Shoulda # :nodoc:
|
|
22
26
|
|
23
27
|
def initialize(attribute)
|
24
28
|
@attribute = attribute
|
25
|
-
@options = {}
|
26
29
|
@submatchers = []
|
27
30
|
|
28
31
|
add_disallow_value_matcher
|
@@ -34,6 +37,18 @@ module Shoulda # :nodoc:
|
|
34
37
|
self
|
35
38
|
end
|
36
39
|
|
40
|
+
def odd
|
41
|
+
odd_number_matcher = OddEvenNumberMatcher.new(@attribute, :odd => true)
|
42
|
+
add_submatcher(odd_number_matcher)
|
43
|
+
self
|
44
|
+
end
|
45
|
+
|
46
|
+
def even
|
47
|
+
even_number_matcher = OddEvenNumberMatcher.new(@attribute, :even => true)
|
48
|
+
add_submatcher(even_number_matcher)
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
37
52
|
def with_message(message)
|
38
53
|
@submatchers.each { |matcher| matcher.with_message(message) }
|
39
54
|
self
|
@@ -49,7 +64,11 @@ module Shoulda # :nodoc:
|
|
49
64
|
end
|
50
65
|
|
51
66
|
def failure_message_for_should
|
52
|
-
|
67
|
+
submatcher_failure_messages_for_should.last
|
68
|
+
end
|
69
|
+
|
70
|
+
def failure_message_for_should_not
|
71
|
+
submatcher_failure_messages_for_should_not.last
|
53
72
|
end
|
54
73
|
|
55
74
|
private
|
@@ -70,10 +89,14 @@ module Shoulda # :nodoc:
|
|
70
89
|
failing_submatchers.empty?
|
71
90
|
end
|
72
91
|
|
73
|
-
def
|
92
|
+
def submatcher_failure_messages_for_should
|
74
93
|
failing_submatchers.map(&:failure_message_for_should)
|
75
94
|
end
|
76
95
|
|
96
|
+
def submatcher_failure_messages_for_should_not
|
97
|
+
failing_submatchers.map(&:failure_message_for_should_not)
|
98
|
+
end
|
99
|
+
|
77
100
|
def failing_submatchers
|
78
101
|
@failing_submatchers ||= @submatchers.select { |matcher| !matcher.matches?(@subject) }
|
79
102
|
end
|
@@ -55,12 +55,26 @@ module Shoulda # :nodoc:
|
|
55
55
|
self
|
56
56
|
end
|
57
57
|
|
58
|
+
def allow_nil
|
59
|
+
@options[:allow_nil] = true
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
63
|
+
def description
|
64
|
+
result = "require "
|
65
|
+
result << "case sensitive " unless @options[:case_insensitive]
|
66
|
+
result << "unique value for #{@attribute}"
|
67
|
+
result << " scoped to #{@options[:scopes].join(', ')}" if @options[:scopes].present?
|
68
|
+
result
|
69
|
+
end
|
70
|
+
|
58
71
|
def matches?(subject)
|
59
72
|
@subject = subject.class.new
|
60
73
|
@expected_message ||= :taken
|
61
74
|
set_scoped_attributes &&
|
62
|
-
|
63
|
-
validate_after_scope_change?
|
75
|
+
validate_everything_except_duplicate_nils? &&
|
76
|
+
validate_after_scope_change? &&
|
77
|
+
allows_nil?
|
64
78
|
end
|
65
79
|
|
66
80
|
def description
|
@@ -73,17 +87,42 @@ module Shoulda # :nodoc:
|
|
73
87
|
|
74
88
|
private
|
75
89
|
|
76
|
-
def
|
77
|
-
@
|
90
|
+
def allows_nil?
|
91
|
+
if @options[:allow_nil]
|
92
|
+
ensure_nil_record_in_database
|
93
|
+
allows_value_of(nil, @expected_message)
|
94
|
+
else
|
95
|
+
true
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def existing_record
|
100
|
+
@existing_record ||= first_instance
|
78
101
|
end
|
79
102
|
|
80
103
|
def first_instance
|
81
|
-
@subject.class.first ||
|
104
|
+
@subject.class.first || create_record_in_database
|
82
105
|
end
|
83
106
|
|
84
|
-
def
|
107
|
+
def ensure_nil_record_in_database
|
108
|
+
unless existing_record_is_nil?
|
109
|
+
create_record_in_database(nil_value: true)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def existing_record_is_nil?
|
114
|
+
@existing_record.present? && existing_value.nil?
|
115
|
+
end
|
116
|
+
|
117
|
+
def create_record_in_database(options = {})
|
118
|
+
if options[:nil_value]
|
119
|
+
value = nil
|
120
|
+
else
|
121
|
+
value = "arbitrary_string"
|
122
|
+
end
|
123
|
+
|
85
124
|
@subject.class.new.tap do |instance|
|
86
|
-
instance.send("#{@attribute}=",
|
125
|
+
instance.send("#{@attribute}=", value)
|
87
126
|
instance.save(:validate => false)
|
88
127
|
end
|
89
128
|
end
|
@@ -93,7 +132,7 @@ module Shoulda # :nodoc:
|
|
93
132
|
@options[:scopes].all? do |scope|
|
94
133
|
setter = :"#{scope}="
|
95
134
|
if @subject.respond_to?(setter)
|
96
|
-
@subject.send(setter,
|
135
|
+
@subject.send(setter, existing_record.send(scope))
|
97
136
|
true
|
98
137
|
else
|
99
138
|
@failure_message_for_should = "#{class_name} doesn't seem to have a #{scope} attribute."
|
@@ -105,10 +144,18 @@ module Shoulda # :nodoc:
|
|
105
144
|
end
|
106
145
|
end
|
107
146
|
|
108
|
-
def
|
147
|
+
def validate_everything_except_duplicate_nils?
|
148
|
+
if @options[:allow_nil] && existing_value.nil?
|
149
|
+
create_record_without_nil
|
150
|
+
end
|
151
|
+
|
109
152
|
disallows_value_of(existing_value, @expected_message)
|
110
153
|
end
|
111
154
|
|
155
|
+
def create_record_without_nil
|
156
|
+
@existing_record = create_record_in_database
|
157
|
+
end
|
158
|
+
|
112
159
|
# TODO: There is a chance that we could change the scoped field
|
113
160
|
# to a value that's already taken. An alternative implementation
|
114
161
|
# could actually find all values for scope and create a unique
|
@@ -117,16 +164,19 @@ module Shoulda # :nodoc:
|
|
117
164
|
true
|
118
165
|
else
|
119
166
|
@options[:scopes].all? do |scope|
|
120
|
-
previous_value =
|
167
|
+
previous_value = existing_record.send(scope)
|
121
168
|
|
122
169
|
# Assume the scope is a foreign key if the field is nil
|
123
170
|
previous_value ||= correct_type_for_column(@subject.class.columns_hash[scope.to_s])
|
124
171
|
|
125
|
-
next_value =
|
126
|
-
previous_value.next
|
127
|
-
|
128
|
-
previous_value.
|
129
|
-
|
172
|
+
next_value =
|
173
|
+
if previous_value.respond_to?(:next)
|
174
|
+
previous_value.next
|
175
|
+
elsif previous_value.respond_to?(:to_datetime)
|
176
|
+
previous_value.to_datetime.next
|
177
|
+
else
|
178
|
+
previous_value.to_s.next
|
179
|
+
end
|
130
180
|
|
131
181
|
@subject.send("#{scope}=", next_value)
|
132
182
|
|
@@ -147,6 +197,8 @@ module Shoulda # :nodoc:
|
|
147
197
|
def correct_type_for_column(column)
|
148
198
|
if column.type == :string
|
149
199
|
'0'
|
200
|
+
elsif column.type == :datetime
|
201
|
+
DateTime.now
|
150
202
|
else
|
151
203
|
0
|
152
204
|
end
|
@@ -157,7 +209,7 @@ module Shoulda # :nodoc:
|
|
157
209
|
end
|
158
210
|
|
159
211
|
def existing_value
|
160
|
-
value =
|
212
|
+
value = existing_record.send(@attribute)
|
161
213
|
if @options[:case_insensitive] && value.respond_to?(:swapcase!)
|
162
214
|
value.swapcase!
|
163
215
|
end
|
@@ -6,9 +6,10 @@ module Shoulda
|
|
6
6
|
class ValidationMessageFinder
|
7
7
|
include Helpers
|
8
8
|
|
9
|
-
def initialize(instance, attribute)
|
9
|
+
def initialize(instance, attribute, context=nil)
|
10
10
|
@instance = instance
|
11
11
|
@attribute = attribute
|
12
|
+
@context = context
|
12
13
|
end
|
13
14
|
|
14
15
|
def allow_description(allowed_values)
|
@@ -58,7 +59,7 @@ module Shoulda
|
|
58
59
|
end
|
59
60
|
|
60
61
|
def validate_instance
|
61
|
-
@instance.valid?
|
62
|
+
@instance.valid?(@context)
|
62
63
|
@instance
|
63
64
|
end
|
64
65
|
end
|
@@ -7,6 +7,8 @@ module Shoulda # :nodoc:
|
|
7
7
|
# * <tt>:class_name</tt> - tests that the association resolves to class_name.
|
8
8
|
# * <tt>:validate</tt> - tests that the association makes use of the validate
|
9
9
|
# option.
|
10
|
+
# * <tt>:touch</tt> - tests that the association makes use of the touch
|
11
|
+
# option.
|
10
12
|
#
|
11
13
|
# Example:
|
12
14
|
# it { should belong_to(:parent) }
|
@@ -107,7 +109,12 @@ module Shoulda # :nodoc:
|
|
107
109
|
end
|
108
110
|
|
109
111
|
def validate(validate = true)
|
110
|
-
@validate = validate
|
112
|
+
@options[:validate] = validate
|
113
|
+
self
|
114
|
+
end
|
115
|
+
|
116
|
+
def touch(touch = true)
|
117
|
+
@options[:touch] = touch
|
111
118
|
self
|
112
119
|
end
|
113
120
|
|
@@ -122,7 +129,8 @@ module Shoulda # :nodoc:
|
|
122
129
|
order_correct? &&
|
123
130
|
conditions_correct? &&
|
124
131
|
join_table_exists? &&
|
125
|
-
validate_correct?
|
132
|
+
validate_correct? &&
|
133
|
+
touch_correct?
|
126
134
|
end
|
127
135
|
|
128
136
|
def failure_message_for_should
|
@@ -258,14 +266,31 @@ module Shoulda # :nodoc:
|
|
258
266
|
end
|
259
267
|
|
260
268
|
def validate_correct?
|
261
|
-
if
|
269
|
+
if option_correct?(:validate)
|
270
|
+
true
|
271
|
+
else
|
272
|
+
@missing = "#{@name} should have :validate => #{@options[:validate]}"
|
273
|
+
false
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
def touch_correct?
|
278
|
+
if option_correct?(:touch)
|
262
279
|
true
|
263
280
|
else
|
264
|
-
@missing = "#{@name} should have :
|
281
|
+
@missing = "#{@name} should have :touch => #{@options[:touch]}"
|
265
282
|
false
|
266
283
|
end
|
267
284
|
end
|
268
285
|
|
286
|
+
def option_correct?(key)
|
287
|
+
!@options.key?(key) || reflection_set_properly_for?(key)
|
288
|
+
end
|
289
|
+
|
290
|
+
def reflection_set_properly_for?(key)
|
291
|
+
@options[key] == !!reflection.options[key]
|
292
|
+
end
|
293
|
+
|
269
294
|
def class_has_foreign_key?(klass)
|
270
295
|
if @options.key?(:foreign_key)
|
271
296
|
reflection.options[:foreign_key] == @options[:foreign_key]
|
data/shoulda-matchers.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
+
s.required_ruby_version = '>= 1.9.2'
|
21
22
|
s.add_dependency('activesupport', '>= 3.0.0')
|
22
23
|
|
23
24
|
s.add_development_dependency('appraisal', '~> 0.4')
|
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoulda::Matchers::ActiveModel::ValidateUniquenessOfMatcher do
|
4
|
+
context "a unique attribute" do
|
5
|
+
before do
|
6
|
+
@model = define_model(:example, :attr => :string,
|
7
|
+
:other => :integer) do
|
8
|
+
attr_accessible :attr, :other
|
9
|
+
validates_uniqueness_of :attr
|
10
|
+
end.new
|
11
|
+
end
|
12
|
+
|
13
|
+
context "with an existing value" do
|
14
|
+
before do
|
15
|
+
@existing = Example.create!(:attr => 'value', :other => 1)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should require a unique value for that attribute" do
|
19
|
+
@model.should validate_uniqueness_of(:attr)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should pass when the subject is an existing record" do
|
23
|
+
@existing.should validate_uniqueness_of(:attr)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should fail when a scope is specified" do
|
27
|
+
@model.should_not validate_uniqueness_of(:attr).scoped_to(:other)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "without an existing value" do
|
32
|
+
before do
|
33
|
+
Example.first.should be_nil
|
34
|
+
@matcher = validate_uniqueness_of(:attr)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "does not not require a created instance" do
|
38
|
+
@model.should @matcher
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "a unique attribute with a custom error and an existing value" do
|
44
|
+
before do
|
45
|
+
@model = define_model(:example, :attr => :string) do
|
46
|
+
attr_accessible :attr
|
47
|
+
validates_uniqueness_of :attr, :message => 'Bad value'
|
48
|
+
end.new
|
49
|
+
Example.create!(:attr => 'value')
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should fail when checking the default message" do
|
53
|
+
@model.should_not validate_uniqueness_of(:attr)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should fail when checking a message that doesn't match" do
|
57
|
+
@model.should_not validate_uniqueness_of(:attr).with_message(/abc/i)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should pass when checking a message that matches" do
|
61
|
+
@model.should validate_uniqueness_of(:attr).with_message(/bad/i)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "a scoped unique attribute with an existing value" do
|
66
|
+
before do
|
67
|
+
@model = define_model(:example, :attr => :string,
|
68
|
+
:scope1 => :integer,
|
69
|
+
:scope2 => :integer,
|
70
|
+
:other => :integer) do
|
71
|
+
attr_accessible :attr, :scope1, :scope2, :other
|
72
|
+
validates_uniqueness_of :attr, :scope => [:scope1, :scope2]
|
73
|
+
end.new
|
74
|
+
@existing = Example.create!(:attr => 'value', :scope1 => 1, :scope2 => 2, :other => 3)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should pass when the correct scope is specified" do
|
78
|
+
@model.should validate_uniqueness_of(:attr).scoped_to(:scope1, :scope2)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should pass when the subject is an existing record" do
|
82
|
+
@existing.should validate_uniqueness_of(:attr).scoped_to(:scope1, :scope2)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should fail when too narrow of a scope is specified" do
|
86
|
+
@model.should_not validate_uniqueness_of(:attr).scoped_to(:scope1, :scope2, :other)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should fail when too broad of a scope is specified" do
|
90
|
+
@model.should_not validate_uniqueness_of(:attr).scoped_to(:scope1)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should fail when a different scope is specified" do
|
94
|
+
@model.should_not validate_uniqueness_of(:attr).scoped_to(:other)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should fail when no scope is specified" do
|
98
|
+
@model.should_not validate_uniqueness_of(:attr)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should fail when a non-existent attribute is specified as a scope" do
|
102
|
+
@model.should_not validate_uniqueness_of(:attr).scoped_to(:fake)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "a non-unique attribute with an existing value" do
|
107
|
+
before do
|
108
|
+
@model = define_model(:example, :attr => :string) do
|
109
|
+
attr_accessible :attr
|
110
|
+
end.new
|
111
|
+
Example.create!(:attr => 'value')
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should not require a unique value for that attribute" do
|
115
|
+
@model.should_not validate_uniqueness_of(:attr)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context "a case sensitive unique attribute with an existing value" do
|
120
|
+
before do
|
121
|
+
@model = define_model(:example, :attr => :string) do
|
122
|
+
attr_accessible :attr
|
123
|
+
validates_uniqueness_of :attr, :case_sensitive => true
|
124
|
+
end.new
|
125
|
+
Example.create!(:attr => 'value')
|
126
|
+
end
|
127
|
+
|
128
|
+
it "should not require a unique, case-insensitive value for that attribute" do
|
129
|
+
@model.should_not validate_uniqueness_of(:attr).case_insensitive
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should require a unique, case-sensitive value for that attribute" do
|
133
|
+
@model.should validate_uniqueness_of(:attr)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "a case sensitive unique integer attribute with an existing value" do
|
138
|
+
before do
|
139
|
+
@model = define_model(:example, :attr => :integer) do
|
140
|
+
attr_accessible :attr
|
141
|
+
validates_uniqueness_of :attr, :case_sensitive => true
|
142
|
+
end.new
|
143
|
+
Example.create!(:attr => 'value')
|
144
|
+
end
|
145
|
+
|
146
|
+
it "should require a unique, case-insensitive value for that attribute" do
|
147
|
+
@model.should validate_uniqueness_of(:attr).case_insensitive
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should require a unique, case-sensitive value for that attribute" do
|
151
|
+
@model.should validate_uniqueness_of(:attr)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context "when the validation allows nil" do
|
156
|
+
before do
|
157
|
+
@model = define_model(:example, :attr => :integer) do
|
158
|
+
attr_accessible :attr
|
159
|
+
validates_uniqueness_of :attr, :allow_nil => true
|
160
|
+
end.new
|
161
|
+
end
|
162
|
+
|
163
|
+
context "when there is an existing entry with a nil" do
|
164
|
+
it "should allow_nil" do
|
165
|
+
Example.create!(:attr => nil)
|
166
|
+
@model.should validate_uniqueness_of(:attr).allow_nil
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
it "should create a nil and verify that it is allowed" do
|
171
|
+
@model.should validate_uniqueness_of(:attr).allow_nil
|
172
|
+
Example.all.any?{ |instance| instance.attr.nil? }
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context "when the validation does not allow a nil" do
|
177
|
+
before do
|
178
|
+
@model = define_model(:example, :attr => :integer) do
|
179
|
+
attr_accessible :attr
|
180
|
+
validates_uniqueness_of :attr
|
181
|
+
end.new
|
182
|
+
end
|
183
|
+
|
184
|
+
context "when there is an existing entry with a nil" do
|
185
|
+
it "should not allow_nil" do
|
186
|
+
Example.create!(:attr => nil)
|
187
|
+
@model.should_not validate_uniqueness_of(:attr).allow_nil
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
it "should not allow_nil" do
|
192
|
+
@model.should_not validate_uniqueness_of(:attr).allow_nil
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|