dm-validations 0.9.2
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/LICENSE +20 -0
- data/README +72 -0
- data/Rakefile +74 -0
- data/TODO +16 -0
- data/lib/dm-validations.rb +208 -0
- data/lib/dm-validations/absent_field_validator.rb +60 -0
- data/lib/dm-validations/acceptance_validator.rb +76 -0
- data/lib/dm-validations/auto_validate.rb +98 -0
- data/lib/dm-validations/confirmation_validator.rb +76 -0
- data/lib/dm-validations/contextual_validators.rb +56 -0
- data/lib/dm-validations/custom_validator.rb +72 -0
- data/lib/dm-validations/format_validator.rb +94 -0
- data/lib/dm-validations/formats/email.rb +40 -0
- data/lib/dm-validations/generic_validator.rb +92 -0
- data/lib/dm-validations/length_validator.rb +113 -0
- data/lib/dm-validations/method_validator.rb +58 -0
- data/lib/dm-validations/numeric_validator.rb +66 -0
- data/lib/dm-validations/primitive_validator.rb +60 -0
- data/lib/dm-validations/required_field_validator.rb +88 -0
- data/lib/dm-validations/support/object.rb +5 -0
- data/lib/dm-validations/uniqueness_validator.rb +61 -0
- data/lib/dm-validations/validation_errors.rb +63 -0
- data/lib/dm-validations/within_validator.rb +41 -0
- data/spec/integration/absent_field_validator_spec.rb +34 -0
- data/spec/integration/acceptance_validator_spec.rb +87 -0
- data/spec/integration/auto_validate_spec.rb +262 -0
- data/spec/integration/confirmation_validator_spec.rb +66 -0
- data/spec/integration/contextual_validators_spec.rb +28 -0
- data/spec/integration/custom_validator_spec.rb +9 -0
- data/spec/integration/format_validator_spec.rb +118 -0
- data/spec/integration/generic_validator_spec.rb +9 -0
- data/spec/integration/length_validator_spec.rb +113 -0
- data/spec/integration/method_validator_spec.rb +31 -0
- data/spec/integration/numeric_validator_spec.rb +192 -0
- data/spec/integration/primitive_validator_spec.rb +25 -0
- data/spec/integration/required_field_validator_spec.rb +93 -0
- data/spec/integration/uniqueness_validator_spec.rb +81 -0
- data/spec/integration/validation_errors_spec.rb +18 -0
- data/spec/integration/validation_spec.rb +339 -0
- data/spec/integration/within_validator_spec.rb +35 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +26 -0
- metadata +104 -0
@@ -0,0 +1,61 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Validate
|
3
|
+
|
4
|
+
##
|
5
|
+
#
|
6
|
+
# @author Guy van den Berg
|
7
|
+
# @since 0.9
|
8
|
+
class UniquenessValidator < GenericValidator
|
9
|
+
include Assertions
|
10
|
+
|
11
|
+
def initialize(field_name, options = {})
|
12
|
+
assert_kind_of 'scope', options[:scope], Array, Symbol if options.has_key?(:scope)
|
13
|
+
super
|
14
|
+
@field_name, @options = field_name, options
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(target)
|
18
|
+
scope = Array(@options[:scope])
|
19
|
+
|
20
|
+
return true if @options[:allow_nil] && target.send(field_name).nil?
|
21
|
+
|
22
|
+
repository_name = target.repository.name
|
23
|
+
|
24
|
+
opts = { field_name => target.validation_property_value(field_name) }
|
25
|
+
|
26
|
+
scope.each do |item|
|
27
|
+
if !target.model.properties(repository_name)[item].nil?
|
28
|
+
opts[item] = target.validation_property_value(item)
|
29
|
+
elsif target.model.relationships(repository_name).has_key?(item)
|
30
|
+
target.validation_association_keys(item).each do |key|
|
31
|
+
opts[key] = target.validation_property_value(key)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
resource = repository(repository_name) { target.model.first(opts) }
|
37
|
+
|
38
|
+
return true if resource.nil?
|
39
|
+
|
40
|
+
# is target and found resource identic? same instance... but not ==
|
41
|
+
return true if resource.repository.name == repository_name && resource.model == target.model && resource.key == target.key
|
42
|
+
|
43
|
+
error_message = @options[:message] || "%s is already taken".t(Extlib::Inflection.humanize(field_name))
|
44
|
+
add_error(target, error_message , field_name)
|
45
|
+
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
end # class UniquenessValidator
|
49
|
+
|
50
|
+
module ValidatesIsUnique
|
51
|
+
|
52
|
+
# Validate the uniqueness of a field
|
53
|
+
#
|
54
|
+
def validates_is_unique(*fields)
|
55
|
+
opts = opts_from_validator_args(fields)
|
56
|
+
add_validator_to_context(opts, fields, DataMapper::Validate::UniquenessValidator)
|
57
|
+
end
|
58
|
+
|
59
|
+
end # module ValidatesIsUnique
|
60
|
+
end # module Validate
|
61
|
+
end # module DataMapper
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Validate
|
3
|
+
|
4
|
+
##
|
5
|
+
#
|
6
|
+
# @author Guy van den Berg
|
7
|
+
# @since 0.9
|
8
|
+
class ValidationErrors
|
9
|
+
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
# Clear existing validation errors.
|
13
|
+
def clear!
|
14
|
+
errors.clear
|
15
|
+
end
|
16
|
+
|
17
|
+
# Add a validation error. Use the field_name :general if the errors does
|
18
|
+
# not apply to a specific field of the Resource.
|
19
|
+
#
|
20
|
+
# @param <Symbol> field_name the name of the field that caused the error
|
21
|
+
# @param <String> message the message to add
|
22
|
+
def add(field_name, message)
|
23
|
+
(errors[field_name] ||= []) << message
|
24
|
+
end
|
25
|
+
|
26
|
+
# Collect all errors into a single list.
|
27
|
+
def full_messages
|
28
|
+
errors.inject([]) do |list,pair|
|
29
|
+
list += pair.last
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Return validation errors for a particular field_name.
|
34
|
+
#
|
35
|
+
# @param <Symbol> field_name the name of the field you want an error for
|
36
|
+
def on(field_name)
|
37
|
+
errors_for_field = errors[field_name]
|
38
|
+
errors_for_field.blank? ? nil : errors_for_field
|
39
|
+
end
|
40
|
+
|
41
|
+
def each
|
42
|
+
errors.map.each do |k,v|
|
43
|
+
next if v.blank?
|
44
|
+
yield(v)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def empty?
|
49
|
+
entries.empty?
|
50
|
+
end
|
51
|
+
|
52
|
+
def method_missing(meth, *args, &block)
|
53
|
+
errors.send(meth, *args, &block)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def errors
|
58
|
+
@errors ||= {}
|
59
|
+
end
|
60
|
+
|
61
|
+
end # class ValidationErrors
|
62
|
+
end # module Validate
|
63
|
+
end # module DataMapper
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Validate
|
3
|
+
|
4
|
+
##
|
5
|
+
#
|
6
|
+
# @author Guy van den Berg
|
7
|
+
# @since 0.9
|
8
|
+
class WithinValidator < GenericValidator
|
9
|
+
|
10
|
+
def initialize(field_name, options={})
|
11
|
+
super
|
12
|
+
@field_name, @options = field_name, options
|
13
|
+
@options[:set] = [] unless @options.has_key?(:set)
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(target)
|
17
|
+
includes = @options[:set].include?(target.send(field_name))
|
18
|
+
return true if includes
|
19
|
+
|
20
|
+
s = ''
|
21
|
+
@options[:set].each {|item| s = s + "#{item}, "}
|
22
|
+
s = '[' + s[0..(s.length-3)] + ']'
|
23
|
+
|
24
|
+
error_message = @options[:message] || "%s must be one of #{s}".t(Extlib::Inflection.humanize(@field_name))
|
25
|
+
add_error(target, error_message , @field_name)
|
26
|
+
return false
|
27
|
+
end
|
28
|
+
end # class WithinValidator
|
29
|
+
|
30
|
+
module ValidatesWithin
|
31
|
+
|
32
|
+
# Validate the absence of a field
|
33
|
+
#
|
34
|
+
def validates_within(*fields)
|
35
|
+
opts = opts_from_validator_args(fields)
|
36
|
+
add_validator_to_context(opts, fields, DataMapper::Validate::WithinValidator)
|
37
|
+
end
|
38
|
+
|
39
|
+
end # module ValidatesWithin
|
40
|
+
end # module Validate
|
41
|
+
end # module DataMapper
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
3
|
+
|
4
|
+
describe DataMapper::Validate::AbsentFieldValidator do
|
5
|
+
before(:all) do
|
6
|
+
class Kayak
|
7
|
+
include DataMapper::Resource
|
8
|
+
property :id, Integer, :key => true
|
9
|
+
property :salesman, String, :auto_validation => false
|
10
|
+
validates_absent :salesman, :when => :sold
|
11
|
+
end
|
12
|
+
|
13
|
+
class Pirogue
|
14
|
+
include DataMapper::Resource
|
15
|
+
property :id, Integer, :key => true
|
16
|
+
property :salesman, String, :default => 'Layfayette'
|
17
|
+
validates_absent :salesman, :when => :sold
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should validate the absence of a value on an instance of a resource" do
|
22
|
+
kayak = Kayak.new
|
23
|
+
kayak.valid_for_sold?.should == true
|
24
|
+
|
25
|
+
kayak.salesman = 'Joe'
|
26
|
+
kayak.valid_for_sold?.should_not == true
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should validate the absence of a value and ensure defaults" do
|
30
|
+
pirogue = Pirogue.new
|
31
|
+
pirogue.should_not be_valid_for_sold
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
3
|
+
|
4
|
+
describe DataMapper::Validate::AcceptanceValidator do
|
5
|
+
describe "with standard options" do
|
6
|
+
before(:all) do
|
7
|
+
class SkimBat
|
8
|
+
include DataMapper::Resource
|
9
|
+
property :id, Integer, :serial => true
|
10
|
+
property :sailyness, Boolean
|
11
|
+
validates_is_accepted :sailyness
|
12
|
+
end
|
13
|
+
@s = SkimBat.new
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should validate if a resource instance has been accepted" do
|
17
|
+
@s.sailyness = "1"
|
18
|
+
@s.valid?.should == true
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should not validate if a resource instance has not been accepted" do
|
22
|
+
@s.sailyness = "0"
|
23
|
+
@s.valid?.should == false
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should allow nil acceptance" do
|
27
|
+
@s.sailyness = nil
|
28
|
+
@s.valid?.should == true
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should add the default message when invalid" do
|
32
|
+
@s.sailyness = "0"
|
33
|
+
@s.valid?.should == false
|
34
|
+
@s.errors.full_messages.join(" ").should =~ /#{DataMapper::Validate::AcceptanceValidator.default_message_for_field("sailyness")}/
|
35
|
+
end
|
36
|
+
end
|
37
|
+
describe "with :allow_nil => false" do
|
38
|
+
before(:all) do
|
39
|
+
SkimBat.class_eval do
|
40
|
+
validators.clear!
|
41
|
+
validates_is_accepted :sailyness, :allow_nil => false
|
42
|
+
end
|
43
|
+
@s = SkimBat.new
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should not allow nil acceptance" do
|
47
|
+
@s.sailyness = nil
|
48
|
+
@s.valid?.should == false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "with custom :accept" do
|
53
|
+
before(:all) do
|
54
|
+
SkimBat.class_eval do
|
55
|
+
validators.clear!
|
56
|
+
validates_is_accepted :sailyness, :accept => "true"
|
57
|
+
end
|
58
|
+
@s = SkimBat.new
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should validate if a resource instance has been accepted" do
|
62
|
+
@s.sailyness = "true"
|
63
|
+
@s.valid?.should == true
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should not validate if a resource instance has not been accepted" do
|
67
|
+
@s.sailyness = "false"
|
68
|
+
@s.valid?.should == false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "with custom message" do
|
73
|
+
before(:all) do
|
74
|
+
SkimBat.class_eval do
|
75
|
+
validators.clear!
|
76
|
+
validates_is_accepted :sailyness, :message => "hehu!"
|
77
|
+
end
|
78
|
+
@s = SkimBat.new
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should append the custom message when invalid" do
|
82
|
+
@s.sailyness = "0"
|
83
|
+
@s.valid?.should == false
|
84
|
+
@s.errors.full_messages.join(" ").should =~ /hehu!/
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,262 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
|
3
|
+
|
4
|
+
module TypecastBypassSetter
|
5
|
+
# Bypass typecasting so we can set values for specs
|
6
|
+
def set(attributes)
|
7
|
+
attributes.each do |k,v|
|
8
|
+
instance_variable_set("@#{k}", v)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class SailBoat
|
14
|
+
include DataMapper::Resource
|
15
|
+
property :id, Integer, :key => true
|
16
|
+
property :name, String, :nullable => false, :validates => :presence_test
|
17
|
+
property :description, String, :length => 10, :validates => :length_test_1
|
18
|
+
property :notes, String, :length => 2..10, :validates => :length_test_2
|
19
|
+
property :no_validation, String, :auto_validation => false
|
20
|
+
property :salesman, String, :nullable => false, :validates => [:multi_context_1, :multi_context_2]
|
21
|
+
property :code, String, :format => Proc.new { |code| code =~ /A\d{4}\z/ }, :validates => :format_test
|
22
|
+
property :allow_nil, String, :size => 5..10, :nullable => true, :validates => :nil_test
|
23
|
+
property :build_date, Date, :validates => :primitive_test
|
24
|
+
property :float, Float, :precision => 2, :scale => 1
|
25
|
+
property :big_decimal, BigDecimal, :precision => 2, :scale => 1
|
26
|
+
|
27
|
+
include TypecastBypassSetter
|
28
|
+
end
|
29
|
+
|
30
|
+
class HasNullableBoolean
|
31
|
+
include DataMapper::Resource
|
32
|
+
property :id, Integer, :key => true
|
33
|
+
property :bool, Boolean # :nullable => true by default
|
34
|
+
|
35
|
+
include TypecastBypassSetter
|
36
|
+
end
|
37
|
+
|
38
|
+
class HasNotNullableBoolean
|
39
|
+
include DataMapper::Resource
|
40
|
+
property :id, Integer, :key => true
|
41
|
+
property :bool, Boolean, :nullable => false
|
42
|
+
|
43
|
+
include TypecastBypassSetter
|
44
|
+
end
|
45
|
+
|
46
|
+
class HasNotNullableParanoidBoolean
|
47
|
+
include DataMapper::Resource
|
48
|
+
property :id, Integer, :key => true
|
49
|
+
property :bool, ParanoidBoolean, :nullable => false
|
50
|
+
|
51
|
+
include TypecastBypassSetter
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "Automatic Validation from Property Definition" do
|
55
|
+
it "should have a hook for adding auto validations called from
|
56
|
+
DataMapper::Property#new" do
|
57
|
+
SailBoat.should respond_to(:auto_generate_validations)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should auto add a validates_is_present when property has option
|
61
|
+
:nullable => false" do
|
62
|
+
validator = SailBoat.validators.context(:presence_test).first
|
63
|
+
validator.should be_kind_of(DataMapper::Validate::RequiredFieldValidator)
|
64
|
+
validator.field_name.should == :name
|
65
|
+
|
66
|
+
boat = SailBoat.new
|
67
|
+
boat.valid_for_presence_test?.should == false
|
68
|
+
boat.name = 'Float'
|
69
|
+
boat.valid_for_presence_test?.should == true
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should auto add a validates_length for maximum size on String properties" do
|
73
|
+
# max length test max=10
|
74
|
+
boat = SailBoat.new
|
75
|
+
boat.valid_for_length_test_1?.should == true #no minimum length
|
76
|
+
boat.description = 'ABCDEFGHIJK' #11
|
77
|
+
boat.valid_for_length_test_1?.should == false
|
78
|
+
boat.description = 'ABCDEFGHIJ' #10
|
79
|
+
boat.valid_for_length_test_1?.should == true
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should auto add validates_length within a range when option :length
|
83
|
+
or :size is a range" do
|
84
|
+
# Range test notes = 2..10
|
85
|
+
boat = SailBoat.new
|
86
|
+
boat.should be_valid_for_length_test_2
|
87
|
+
boat.notes = 'AB' #2
|
88
|
+
boat.should be_valid_for_length_test_2
|
89
|
+
boat.notes = 'ABCDEFGHIJK' #11
|
90
|
+
boat.should_not be_valid_for_length_test_2
|
91
|
+
boat.notes = 'ABCDEFGHIJ' #10
|
92
|
+
boat.should be_valid_for_length_test_2
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should auto add a validates_format if the :format option is given" do
|
96
|
+
# format test - format = /A\d{4}\z/ on code
|
97
|
+
boat = SailBoat.new
|
98
|
+
boat.should be_valid_for_format_test
|
99
|
+
boat.code = 'A1234'
|
100
|
+
boat.should be_valid_for_format_test
|
101
|
+
boat.code = 'BAD CODE'
|
102
|
+
boat.should_not be_valid_for_format_test
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should auto validate all strings for max length" do
|
106
|
+
klass = Class.new do
|
107
|
+
include DataMapper::Resource
|
108
|
+
property :id, Integer, :serial => true
|
109
|
+
property :name, String
|
110
|
+
end
|
111
|
+
t = klass.new(:id => 1)
|
112
|
+
t.should be_valid
|
113
|
+
t.name = 'Lipsmackinthirstquenchinacetastinmotivatingoodbuzzincooltalkinhighwalkinfastlivinevergivincoolfizzin'
|
114
|
+
t.should_not be_valid
|
115
|
+
t.errors.full_messages.should include('Name must be less than 50 characters long')
|
116
|
+
end
|
117
|
+
|
118
|
+
it "should auto validate the primitive type" do
|
119
|
+
validator = SailBoat.validators.context(:primitive_test).first
|
120
|
+
validator.should be_kind_of(DataMapper::Validate::PrimitiveValidator)
|
121
|
+
boat = SailBoat.new
|
122
|
+
boat.should be_valid_for_primitive_test
|
123
|
+
boat.build_date = 'ABC'
|
124
|
+
boat.should_not be_valid_for_primitive_test
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should not auto add any validators if the option :auto_validation => false was given" do
|
128
|
+
klass = Class.new do
|
129
|
+
include DataMapper::Resource
|
130
|
+
property :id, Integer, :serial => true, :auto_validation => false
|
131
|
+
property :name, String, :nullable => false, :auto_validation => false
|
132
|
+
property :bool, DM::Boolean, :nullable => false, :auto_validation => false
|
133
|
+
end
|
134
|
+
klass.new.valid?.should == true
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should auto add range checking the length of a string while still allowing null values" do
|
138
|
+
boat = SailBoat.new
|
139
|
+
boat.allow_nil = 'ABC'
|
140
|
+
boat.should_not be_valid_for_nil_test
|
141
|
+
boat.errors.on(:allow_nil).should include('Allow nil must be between 5 and 10 characters long')
|
142
|
+
|
143
|
+
boat.allow_nil = 'ABCDEFG'
|
144
|
+
boat.should be_valid_for_nil_test
|
145
|
+
|
146
|
+
boat.allow_nil = 'ABCDEFGHIJKLMNOP'
|
147
|
+
boat.should_not be_valid_for_nil_test
|
148
|
+
boat.errors.on(:allow_nil).should include('Allow nil must be between 5 and 10 characters long')
|
149
|
+
|
150
|
+
boat.allow_nil = nil
|
151
|
+
boat.should be_valid_for_nil_test
|
152
|
+
end
|
153
|
+
|
154
|
+
describe 'for Integer properties' do
|
155
|
+
before do
|
156
|
+
@boat = SailBoat.new
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should allow integers' do
|
160
|
+
@boat.set(:id => 1)
|
161
|
+
@boat.should be_valid
|
162
|
+
end
|
163
|
+
|
164
|
+
it 'should not allow floats' do
|
165
|
+
@boat.set(:id => 1.0)
|
166
|
+
@boat.should_not be_valid
|
167
|
+
@boat.errors.on(:id).should == [ 'Id must be an integer' ]
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'should not allow decimals' do
|
171
|
+
@boat.set(:id => BigDecimal('1'))
|
172
|
+
@boat.should_not be_valid
|
173
|
+
@boat.errors.on(:id).should == [ 'Id must be an integer' ]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
describe 'for nullable Boolean properties' do
|
178
|
+
before do
|
179
|
+
@boat = HasNullableBoolean.new(:id => 1)
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'should allow true' do
|
183
|
+
@boat.set(:bool => true)
|
184
|
+
@boat.should be_valid
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'should allow false' do
|
188
|
+
@boat.set(:bool => false)
|
189
|
+
@boat.should be_valid
|
190
|
+
end
|
191
|
+
|
192
|
+
it 'should allow nil' do
|
193
|
+
@boat.set(:bool => nil)
|
194
|
+
@boat.should be_valid
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
describe 'for non-nullable Boolean properties' do
|
199
|
+
before do
|
200
|
+
@boat = HasNotNullableBoolean.new(:id => 1)
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'should allow true' do
|
204
|
+
@boat.set(:bool => true)
|
205
|
+
@boat.should be_valid
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'should allow false' do
|
209
|
+
@boat.set(:bool => false)
|
210
|
+
@boat.should be_valid
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'should not allow nil' do
|
214
|
+
@boat.set(:bool => nil)
|
215
|
+
@boat.should_not be_valid
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
describe 'for non-nullable ParanoidBoolean properties' do
|
220
|
+
before do
|
221
|
+
@boat = HasNotNullableParanoidBoolean.new(:id => 1)
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'should allow true' do
|
225
|
+
@boat.set(:bool => true)
|
226
|
+
@boat.should be_valid
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'should allow false' do
|
230
|
+
@boat.set(:bool => false)
|
231
|
+
@boat.should be_valid
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'should not allow nil' do
|
235
|
+
@boat.set(:bool => nil)
|
236
|
+
@boat.should_not be_valid
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
{ :float => Float, :big_decimal => BigDecimal }.each do |column,type|
|
241
|
+
describe "for #{type} properties" do
|
242
|
+
before do
|
243
|
+
@boat = SailBoat.new(:id => 1)
|
244
|
+
end
|
245
|
+
|
246
|
+
it 'should allow integers' do
|
247
|
+
@boat.set(column => 1)
|
248
|
+
@boat.should be_valid
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'should allow floats' do
|
252
|
+
@boat.set(column => '1.0')
|
253
|
+
@boat.should be_valid
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'should allow decimals' do
|
257
|
+
@boat.set(column => BigDecimal('1'))
|
258
|
+
@boat.should be_valid
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|