ardm-validations 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +35 -0
- data/.travis.yml +11 -0
- data/Gemfile +51 -0
- data/LICENSE +21 -0
- data/README.rdoc +122 -0
- data/Rakefile +4 -0
- data/ardm-validations.gemspec +28 -0
- data/lib/ardm-validations.rb +1 -0
- data/lib/dm-validations.rb +169 -0
- data/lib/dm-validations/auto_validate.rb +252 -0
- data/lib/dm-validations/context.rb +66 -0
- data/lib/dm-validations/contextual_validators.rb +220 -0
- data/lib/dm-validations/exceptions.rb +5 -0
- data/lib/dm-validations/formats/email.rb +65 -0
- data/lib/dm-validations/formats/url.rb +27 -0
- data/lib/dm-validations/support/object.rb +18 -0
- data/lib/dm-validations/support/ordered_hash.rb +434 -0
- data/lib/dm-validations/validation_errors.rb +137 -0
- data/lib/dm-validations/validators/absent_field_validator.rb +58 -0
- data/lib/dm-validations/validators/acceptance_validator.rb +79 -0
- data/lib/dm-validations/validators/block_validator.rb +61 -0
- data/lib/dm-validations/validators/confirmation_validator.rb +92 -0
- data/lib/dm-validations/validators/format_validator.rb +124 -0
- data/lib/dm-validations/validators/generic_validator.rb +184 -0
- data/lib/dm-validations/validators/length_validator.rb +249 -0
- data/lib/dm-validations/validators/method_validator.rb +64 -0
- data/lib/dm-validations/validators/numeric_validator.rb +182 -0
- data/lib/dm-validations/validators/primitive_validator.rb +58 -0
- data/lib/dm-validations/validators/required_field_validator.rb +83 -0
- data/lib/dm-validations/validators/uniqueness_validator.rb +67 -0
- data/lib/dm-validations/validators/within_validator.rb +74 -0
- data/lib/dm-validations/version.rb +5 -0
- data/spec/fixtures/barcode.rb +40 -0
- data/spec/fixtures/basketball_court.rb +58 -0
- data/spec/fixtures/basketball_player.rb +34 -0
- data/spec/fixtures/beta_tester_account.rb +33 -0
- data/spec/fixtures/bill_of_landing.rb +47 -0
- data/spec/fixtures/boat_dock.rb +26 -0
- data/spec/fixtures/city.rb +24 -0
- data/spec/fixtures/company.rb +93 -0
- data/spec/fixtures/corporate_world.rb +39 -0
- data/spec/fixtures/country.rb +24 -0
- data/spec/fixtures/ethernet_frame.rb +56 -0
- data/spec/fixtures/event.rb +44 -0
- data/spec/fixtures/g3_concert.rb +57 -0
- data/spec/fixtures/jabberwock.rb +27 -0
- data/spec/fixtures/kayak.rb +28 -0
- data/spec/fixtures/lernean_hydra.rb +39 -0
- data/spec/fixtures/llama_spaceship.rb +15 -0
- data/spec/fixtures/mathematical_function.rb +34 -0
- data/spec/fixtures/memory_object.rb +30 -0
- data/spec/fixtures/mittelschnauzer.rb +39 -0
- data/spec/fixtures/motor_launch.rb +21 -0
- data/spec/fixtures/multibyte.rb +16 -0
- data/spec/fixtures/page.rb +32 -0
- data/spec/fixtures/phone_number.rb +28 -0
- data/spec/fixtures/pirogue.rb +28 -0
- data/spec/fixtures/programming_language.rb +83 -0
- data/spec/fixtures/reservation.rb +38 -0
- data/spec/fixtures/scm_operation.rb +56 -0
- data/spec/fixtures/sms_message.rb +22 -0
- data/spec/fixtures/udp_packet.rb +49 -0
- data/spec/integration/absent_field_validator/absent_field_validator_spec.rb +90 -0
- data/spec/integration/absent_field_validator/spec_helper.rb +7 -0
- data/spec/integration/acceptance_validator/acceptance_validator_spec.rb +196 -0
- data/spec/integration/acceptance_validator/spec_helper.rb +7 -0
- data/spec/integration/automatic_validation/custom_messages_for_inferred_validation_spec.rb +57 -0
- data/spec/integration/automatic_validation/disabling_inferred_validation_spec.rb +49 -0
- data/spec/integration/automatic_validation/inferred_boolean_properties_validation_spec.rb +100 -0
- data/spec/integration/automatic_validation/inferred_float_property_validation_spec.rb +45 -0
- data/spec/integration/automatic_validation/inferred_format_validation_spec.rb +35 -0
- data/spec/integration/automatic_validation/inferred_integer_properties_validation_spec.rb +70 -0
- data/spec/integration/automatic_validation/inferred_length_validation_spec.rb +142 -0
- data/spec/integration/automatic_validation/inferred_presence_validation_spec.rb +45 -0
- data/spec/integration/automatic_validation/inferred_primitive_validation_spec.rb +22 -0
- data/spec/integration/automatic_validation/inferred_uniqueness_validation_spec.rb +52 -0
- data/spec/integration/automatic_validation/inferred_within_validation_spec.rb +39 -0
- data/spec/integration/automatic_validation/spec_helper.rb +57 -0
- data/spec/integration/block_validator/block_validator_spec.rb +32 -0
- data/spec/integration/block_validator/spec_helper.rb +5 -0
- data/spec/integration/conditional_validation/if_condition_spec.rb +63 -0
- data/spec/integration/conditional_validation/spec_helper.rb +5 -0
- data/spec/integration/confirmation_validator/confirmation_validator_spec.rb +76 -0
- data/spec/integration/confirmation_validator/spec_helper.rb +5 -0
- data/spec/integration/datamapper_models/association_validation_spec.rb +29 -0
- data/spec/integration/datamapper_models/inheritance_spec.rb +82 -0
- data/spec/integration/dirty_attributes/dirty_attributes_spec.rb +13 -0
- data/spec/integration/duplicated_validations/duplicated_validations_spec.rb +24 -0
- data/spec/integration/duplicated_validations/spec_helper.rb +5 -0
- data/spec/integration/format_validator/email_format_validator_spec.rb +139 -0
- data/spec/integration/format_validator/format_validator_spec.rb +64 -0
- data/spec/integration/format_validator/regexp_validator_spec.rb +33 -0
- data/spec/integration/format_validator/spec_helper.rb +5 -0
- data/spec/integration/format_validator/url_format_validator_spec.rb +93 -0
- data/spec/integration/length_validator/default_value_spec.rb +14 -0
- data/spec/integration/length_validator/equality_spec.rb +87 -0
- data/spec/integration/length_validator/error_message_spec.rb +22 -0
- data/spec/integration/length_validator/maximum_spec.rb +49 -0
- data/spec/integration/length_validator/minimum_spec.rb +54 -0
- data/spec/integration/length_validator/range_spec.rb +87 -0
- data/spec/integration/length_validator/spec_helper.rb +7 -0
- data/spec/integration/method_validator/method_validator_spec.rb +241 -0
- data/spec/integration/method_validator/spec_helper.rb +5 -0
- data/spec/integration/numeric_validator/equality_with_float_type_spec.rb +65 -0
- data/spec/integration/numeric_validator/equality_with_integer_type_spec.rb +41 -0
- data/spec/integration/numeric_validator/float_type_spec.rb +90 -0
- data/spec/integration/numeric_validator/gt_with_float_type_spec.rb +37 -0
- data/spec/integration/numeric_validator/gte_with_float_type_spec.rb +37 -0
- data/spec/integration/numeric_validator/integer_only_true_spec.rb +91 -0
- data/spec/integration/numeric_validator/integer_type_spec.rb +86 -0
- data/spec/integration/numeric_validator/lt_with_float_type_spec.rb +37 -0
- data/spec/integration/numeric_validator/lte_with_float_type_spec.rb +37 -0
- data/spec/integration/numeric_validator/spec_helper.rb +5 -0
- data/spec/integration/primitive_validator/primitive_validator_spec.rb +92 -0
- data/spec/integration/primitive_validator/spec_helper.rb +5 -0
- data/spec/integration/pure_ruby_objects/plain_old_ruby_object_validation_spec.rb +118 -0
- data/spec/integration/required_field_validator/association_spec.rb +72 -0
- data/spec/integration/required_field_validator/boolean_type_value_spec.rb +155 -0
- data/spec/integration/required_field_validator/date_type_value_spec.rb +127 -0
- data/spec/integration/required_field_validator/datetime_type_value_spec.rb +127 -0
- data/spec/integration/required_field_validator/float_type_value_spec.rb +131 -0
- data/spec/integration/required_field_validator/integer_type_value_spec.rb +99 -0
- data/spec/integration/required_field_validator/plain_old_ruby_object_spec.rb +35 -0
- data/spec/integration/required_field_validator/shared_examples.rb +26 -0
- data/spec/integration/required_field_validator/spec_helper.rb +7 -0
- data/spec/integration/required_field_validator/string_type_value_spec.rb +167 -0
- data/spec/integration/required_field_validator/text_type_value_spec.rb +49 -0
- data/spec/integration/shared/default_validation_context.rb +13 -0
- data/spec/integration/shared/valid_and_invalid_model.rb +35 -0
- data/spec/integration/uniqueness_validator/spec_helper.rb +5 -0
- data/spec/integration/uniqueness_validator/uniqueness_validator_spec.rb +116 -0
- data/spec/integration/within_validator/spec_helper.rb +5 -0
- data/spec/integration/within_validator/within_validator_spec.rb +168 -0
- data/spec/public/resource_spec.rb +105 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/unit/contextual_validators/emptiness_spec.rb +50 -0
- data/spec/unit/contextual_validators/execution_spec.rb +48 -0
- data/spec/unit/contextual_validators/spec_helper.rb +37 -0
- data/spec/unit/generic_validator/equality_operator_spec.rb +26 -0
- data/spec/unit/generic_validator/optional_spec.rb +54 -0
- data/spec/unit/validation_errors/adding_spec.rb +54 -0
- data/spec/unit/validation_errors/emptiness_spec.rb +38 -0
- data/spec/unit/validation_errors/enumerable_spec.rb +32 -0
- data/spec/unit/validation_errors/reading_spec.rb +35 -0
- data/spec/unit/validation_errors/respond_to_spec.rb +15 -0
- data/spec/unit/validators/within_validator_spec.rb +23 -0
- data/tasks/spec.rake +38 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +256 -0
@@ -0,0 +1,182 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Validations
|
3
|
+
# @author Guy van den Berg
|
4
|
+
# @since 0.9
|
5
|
+
class NumericalityValidator < GenericValidator
|
6
|
+
|
7
|
+
def call(target)
|
8
|
+
value = target.validation_property_value(field_name)
|
9
|
+
return true if optional?(value)
|
10
|
+
|
11
|
+
errors = []
|
12
|
+
|
13
|
+
validate_with(integer_only? ? :integer : :numeric, value, errors)
|
14
|
+
|
15
|
+
add_errors(target, errors)
|
16
|
+
|
17
|
+
# if the number is invalid, skip further tests
|
18
|
+
return false if errors.any?
|
19
|
+
|
20
|
+
[ :gt, :lt, :gte, :lte, :eq, :ne ].each do |validation_type|
|
21
|
+
validate_with(validation_type, value, errors)
|
22
|
+
end
|
23
|
+
|
24
|
+
add_errors(target, errors)
|
25
|
+
|
26
|
+
errors.empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def integer_only?
|
32
|
+
options[:only_integer] || options.fetch(:integer_only, false)
|
33
|
+
end
|
34
|
+
|
35
|
+
def value_as_string(value)
|
36
|
+
case value
|
37
|
+
# Avoid Scientific Notation in Float to_s
|
38
|
+
when Float then value.to_d.to_s('F')
|
39
|
+
when BigDecimal then value.to_s('F')
|
40
|
+
else value.to_s
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_errors(target, errors)
|
45
|
+
return if errors.empty?
|
46
|
+
|
47
|
+
if options.key?(:message)
|
48
|
+
add_error(target, options[:message], field_name)
|
49
|
+
else
|
50
|
+
errors.each do |error_message|
|
51
|
+
add_error(target, error_message, field_name)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate_with(validation_type, value, errors)
|
57
|
+
send("validate_#{validation_type}", value, errors)
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_with_comparison(value, cmp, expected, error_message_name, errors, negated = false)
|
61
|
+
return if expected.nil?
|
62
|
+
|
63
|
+
# XXX: workaround for jruby. This is needed because the jruby
|
64
|
+
# compiler optimizes a bit too far with magic variables like $~.
|
65
|
+
# the value.send line sends $~. Inserting this line makes sure the
|
66
|
+
# jruby compiler does not optimise here.
|
67
|
+
# see http://jira.codehaus.org/browse/JRUBY-3765
|
68
|
+
$~ = nil if RUBY_PLATFORM[/java/]
|
69
|
+
|
70
|
+
comparison = value.send(cmp, expected)
|
71
|
+
return if negated ? !comparison : comparison
|
72
|
+
|
73
|
+
errors << ValidationErrors.default_error_message(
|
74
|
+
error_message_name,
|
75
|
+
field_name,
|
76
|
+
expected
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate_integer(value, errors)
|
81
|
+
validate_with_comparison(value_as_string(value), :=~, /\A[+-]?\d+\z/, :not_an_integer, errors)
|
82
|
+
end
|
83
|
+
|
84
|
+
def validate_numeric(value, errors)
|
85
|
+
precision = options[:precision]
|
86
|
+
scale = options[:scale]
|
87
|
+
|
88
|
+
regexp = if precision && scale
|
89
|
+
if precision > scale && scale == 0
|
90
|
+
/\A[+-]?(?:\d{1,#{precision}}(?:\.0)?)\z/
|
91
|
+
elsif precision > scale
|
92
|
+
/\A[+-]?(?:\d{1,#{precision - scale}}|\d{0,#{precision - scale}}\.\d{1,#{scale}})\z/
|
93
|
+
elsif precision == scale
|
94
|
+
/\A[+-]?(?:0(?:\.\d{1,#{scale}})?)\z/
|
95
|
+
else
|
96
|
+
raise ArgumentError, "Invalid precision #{precision.inspect} and scale #{scale.inspect} for #{field_name} (value: #{value.inspect} #{value.class})"
|
97
|
+
end
|
98
|
+
else
|
99
|
+
/\A[+-]?(?:\d+|\d*\.\d+)\z/
|
100
|
+
end
|
101
|
+
|
102
|
+
validate_with_comparison(value_as_string(value), :=~, regexp, :not_a_number, errors)
|
103
|
+
end
|
104
|
+
|
105
|
+
def validate_gt(value, errors)
|
106
|
+
validate_with_comparison(value, :>, options[:gt] || options[:greater_than], :greater_than, errors)
|
107
|
+
end
|
108
|
+
|
109
|
+
def validate_lt(value, errors)
|
110
|
+
validate_with_comparison(value, :<, options[:lt] || options[:less_than], :less_than, errors)
|
111
|
+
end
|
112
|
+
|
113
|
+
def validate_gte(value, errors)
|
114
|
+
validate_with_comparison(value, :>=, options[:gte] || options[:greater_than_or_equal_to], :greater_than_or_equal_to, errors)
|
115
|
+
end
|
116
|
+
|
117
|
+
def validate_lte(value, errors)
|
118
|
+
validate_with_comparison(value, :<=, options[:lte] || options[:less_than_or_equal_to], :less_than_or_equal_to, errors)
|
119
|
+
end
|
120
|
+
|
121
|
+
def validate_eq(value, errors)
|
122
|
+
eq = options[:eq] || options[:equal] || options[:equals] || options[:exactly] || options[:equal_to]
|
123
|
+
validate_with_comparison(value, :==, eq, :equal_to, errors)
|
124
|
+
end
|
125
|
+
|
126
|
+
def validate_ne(value, errors)
|
127
|
+
validate_with_comparison(value, :==, options[:ne] || options[:not_equal_to], :not_equal_to, errors, true)
|
128
|
+
end
|
129
|
+
|
130
|
+
end # class NumericalityValidator
|
131
|
+
|
132
|
+
module ValidatesNumericality
|
133
|
+
extend Deprecate
|
134
|
+
|
135
|
+
# Validate whether a field is numeric.
|
136
|
+
#
|
137
|
+
# @option [Boolean] :allow_nil
|
138
|
+
# true if number can be nil, false if not.
|
139
|
+
#
|
140
|
+
# @option [Boolean] :allow_blank
|
141
|
+
# true if number can be blank, false if not.
|
142
|
+
#
|
143
|
+
# @option [String] :message
|
144
|
+
# Custom error message, also can be a callable object that takes
|
145
|
+
# an object (for pure Ruby objects) or object and property
|
146
|
+
# (for DM resources).
|
147
|
+
#
|
148
|
+
# @option [Numeric] :precision
|
149
|
+
# Required precision of a value.
|
150
|
+
#
|
151
|
+
# @option [Numeric] :scale
|
152
|
+
# Required scale of a value.
|
153
|
+
#
|
154
|
+
# @option [Numeric] :gte
|
155
|
+
# 'Greater than or equal to' requirement.
|
156
|
+
#
|
157
|
+
# @option [Numeric] :lte
|
158
|
+
# 'Less than or equal to' requirement.
|
159
|
+
#
|
160
|
+
# @option [Numeric] :lt
|
161
|
+
# 'Less than' requirement.
|
162
|
+
#
|
163
|
+
# @option [Numeric] :gt
|
164
|
+
# 'Greater than' requirement.
|
165
|
+
#
|
166
|
+
# @option [Numeric] :eq
|
167
|
+
# 'Equal' requirement.
|
168
|
+
#
|
169
|
+
# @option [Numeric] :ne
|
170
|
+
# 'Not equal' requirement.
|
171
|
+
#
|
172
|
+
# @option [Boolean] :integer_only
|
173
|
+
# Use to restrict allowed values to integers.
|
174
|
+
#
|
175
|
+
def validates_numericality_of(*fields)
|
176
|
+
validators.add(NumericalityValidator, *fields)
|
177
|
+
end
|
178
|
+
|
179
|
+
deprecate :validates_is_number, :validates_numericality_of
|
180
|
+
end # module ValidatesIsNumber
|
181
|
+
end # module Validations
|
182
|
+
end # module DataMapper
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Validations
|
3
|
+
# @author Dirkjan Bussink
|
4
|
+
# @since 0.9
|
5
|
+
class PrimitiveTypeValidator < GenericValidator
|
6
|
+
|
7
|
+
def call(target)
|
8
|
+
value = target.validation_property_value(field_name)
|
9
|
+
property = get_resource_property(target, field_name)
|
10
|
+
|
11
|
+
return true if value.nil? || property.primitive?(value)
|
12
|
+
|
13
|
+
error_message = @options[:message] || default_error(property)
|
14
|
+
add_error(target, error_message, field_name)
|
15
|
+
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def default_error(property)
|
22
|
+
ValidationErrors.default_error_message(
|
23
|
+
:primitive,
|
24
|
+
field_name,
|
25
|
+
property.primitive
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
end # class PrimitiveTypeValidator
|
30
|
+
|
31
|
+
module ValidatesPrimitiveType
|
32
|
+
extend Deprecate
|
33
|
+
|
34
|
+
# Validates that the specified attribute is of the correct primitive
|
35
|
+
# type.
|
36
|
+
#
|
37
|
+
# @example Usage
|
38
|
+
# require 'dm-validations'
|
39
|
+
#
|
40
|
+
# class Person
|
41
|
+
# include DataMapper::Resource
|
42
|
+
#
|
43
|
+
# property :birth_date, Date
|
44
|
+
#
|
45
|
+
# validates_primitive_type_of :birth_date
|
46
|
+
#
|
47
|
+
# # a call to valid? will return false unless
|
48
|
+
# # the birth_date is something that can be properly
|
49
|
+
# # casted into a Date object.
|
50
|
+
# end
|
51
|
+
def validates_primitive_type_of(*fields)
|
52
|
+
validators.add(PrimitiveTypeValidator, *fields)
|
53
|
+
end
|
54
|
+
|
55
|
+
deprecate :validates_is_primitive, :validates_primitive_type_of
|
56
|
+
end # module ValidatesPresent
|
57
|
+
end # module Validations
|
58
|
+
end # module DataMapper
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Validations
|
3
|
+
# @author Guy van den Berg
|
4
|
+
# @since 0.9
|
5
|
+
class PresenceValidator < GenericValidator
|
6
|
+
|
7
|
+
def call(target)
|
8
|
+
value = target.validation_property_value(field_name)
|
9
|
+
property = get_resource_property(target, field_name)
|
10
|
+
return true if present?(value, property)
|
11
|
+
|
12
|
+
error_message = @options[:message] || default_error(property)
|
13
|
+
add_error(target, error_message, field_name)
|
14
|
+
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
protected
|
19
|
+
|
20
|
+
# Boolean property types are considered present if non-nil.
|
21
|
+
# Other property types are considered present if non-blank.
|
22
|
+
# Non-properties are considered present if non-blank.
|
23
|
+
def present?(value, property)
|
24
|
+
boolean_type?(property) ? !value.nil? : !DataMapper::Ext.blank?(value)
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_error(property)
|
28
|
+
actual = boolean_type?(property) ? :nil : :blank
|
29
|
+
ValidationErrors.default_error_message(actual, field_name)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Is the property a boolean property?
|
33
|
+
#
|
34
|
+
# @return [Boolean]
|
35
|
+
# Returns true for Boolean, ParanoidBoolean, TrueClass and other
|
36
|
+
# properties. Returns false for other property types or for
|
37
|
+
# non-properties.
|
38
|
+
def boolean_type?(property)
|
39
|
+
property ? property.primitive == TrueClass : false
|
40
|
+
end
|
41
|
+
|
42
|
+
end # class PresenceValidator
|
43
|
+
|
44
|
+
module ValidatesPresence
|
45
|
+
extend Deprecate
|
46
|
+
|
47
|
+
##
|
48
|
+
# Validates that the specified attribute is present.
|
49
|
+
#
|
50
|
+
# For most property types "being present" is the same as being "not
|
51
|
+
# blank" as determined by the attribute's #blank? method. However, in
|
52
|
+
# the case of Boolean, "being present" means not nil; i.e. true or
|
53
|
+
# false.
|
54
|
+
#
|
55
|
+
# @note
|
56
|
+
# dm-core's support lib adds the blank? method to many classes,
|
57
|
+
#
|
58
|
+
# @see lib/dm-core/support/blank.rb (dm-core) for more information.
|
59
|
+
#
|
60
|
+
# @example Usage
|
61
|
+
# require 'dm-validations'
|
62
|
+
#
|
63
|
+
# class Page
|
64
|
+
# include DataMapper::Resource
|
65
|
+
#
|
66
|
+
# property :required_attribute, String
|
67
|
+
# property :another_required, String
|
68
|
+
# property :yet_again, String
|
69
|
+
#
|
70
|
+
# validates_presence_of :required_attribute
|
71
|
+
# validates_presence_of :another_required, :yet_again
|
72
|
+
#
|
73
|
+
# # a call to valid? will return false unless
|
74
|
+
# # all three attributes are !blank?
|
75
|
+
# end
|
76
|
+
def validates_presence_of(*fields)
|
77
|
+
validators.add(PresenceValidator, *fields)
|
78
|
+
end
|
79
|
+
|
80
|
+
deprecate :validates_present, :validates_presence_of
|
81
|
+
end # module ValidatesPresent
|
82
|
+
end # module Validations
|
83
|
+
end # module DataMapper
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Validations
|
3
|
+
# @author Guy van den Berg
|
4
|
+
# @since 0.9
|
5
|
+
class UniquenessValidator < GenericValidator
|
6
|
+
|
7
|
+
include DataMapper::Assertions
|
8
|
+
|
9
|
+
def initialize(field_name, options = {})
|
10
|
+
if options.has_key?(:scope)
|
11
|
+
assert_kind_of('scope', options[:scope], Array, Symbol)
|
12
|
+
end
|
13
|
+
|
14
|
+
super
|
15
|
+
|
16
|
+
set_optional_by_default
|
17
|
+
end
|
18
|
+
|
19
|
+
def call(target)
|
20
|
+
return true if valid?(target)
|
21
|
+
|
22
|
+
error_message = @options[:message] || ValidationErrors.default_error_message(:taken, field_name)
|
23
|
+
add_error(target, error_message, field_name)
|
24
|
+
|
25
|
+
false
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid?(target)
|
29
|
+
value = target.validation_property_value(field_name)
|
30
|
+
return true if optional?(value)
|
31
|
+
|
32
|
+
opts = {
|
33
|
+
:fields => target.model.key(target.repository.name),
|
34
|
+
field_name => value,
|
35
|
+
}
|
36
|
+
|
37
|
+
Array(@options[:scope]).each { |subject|
|
38
|
+
unless target.respond_to?(subject)
|
39
|
+
raise(ArgumentError,"Could not find property to scope by: #{subject}. Note that :unique does not currently support arbitrarily named groups, for that you should use :unique_index with an explicit validates_uniqueness_of.")
|
40
|
+
end
|
41
|
+
|
42
|
+
opts[subject] = target.__send__(subject)
|
43
|
+
}
|
44
|
+
|
45
|
+
resource = DataMapper.repository(target.repository.name) do
|
46
|
+
target.model.first(opts)
|
47
|
+
end
|
48
|
+
|
49
|
+
return true if resource.nil?
|
50
|
+
target.saved? && resource.key == target.key
|
51
|
+
end
|
52
|
+
|
53
|
+
end # class UniquenessValidator
|
54
|
+
|
55
|
+
module ValidatesUniqueness
|
56
|
+
extend Deprecate
|
57
|
+
|
58
|
+
# Validate the uniqueness of a field
|
59
|
+
#
|
60
|
+
def validates_uniqueness_of(*fields)
|
61
|
+
validators.add(UniquenessValidator, *fields)
|
62
|
+
end
|
63
|
+
|
64
|
+
deprecate :validates_is_unique, :validates_uniqueness_of
|
65
|
+
end # module ValidatesIsUnique
|
66
|
+
end # module Validations
|
67
|
+
end # module DataMapper
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Validations
|
3
|
+
# @author Guy van den Berg
|
4
|
+
# @since 0.9
|
5
|
+
class WithinValidator < GenericValidator
|
6
|
+
|
7
|
+
def initialize(field_name, options={})
|
8
|
+
super
|
9
|
+
|
10
|
+
@options[:set] = [] unless @options.has_key?(:set)
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(target)
|
14
|
+
value = target.validation_property_value(field_name)
|
15
|
+
return true if optional?(value)
|
16
|
+
return true if @options[:set].include?(value)
|
17
|
+
|
18
|
+
n = 1.0/0
|
19
|
+
set = @options[:set]
|
20
|
+
msg = @options[:message]
|
21
|
+
|
22
|
+
if set.is_a?(Range)
|
23
|
+
if set.first != -n && set.last != n
|
24
|
+
error_message = msg || ValidationErrors.default_error_message(:value_between, field_name, set.first, set.last)
|
25
|
+
elsif set.first == -n
|
26
|
+
error_message = msg || ValidationErrors.default_error_message(:less_than_or_equal_to, field_name, set.last)
|
27
|
+
elsif set.last == n
|
28
|
+
error_message = msg || ValidationErrors.default_error_message(:greater_than_or_equal_to, field_name, set.first)
|
29
|
+
end
|
30
|
+
else
|
31
|
+
error_message = msg || ValidationErrors.default_error_message(:inclusion, field_name, set.to_a.join(', '))
|
32
|
+
end
|
33
|
+
|
34
|
+
add_error(target, error_message, field_name)
|
35
|
+
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
end # class WithinValidator
|
41
|
+
|
42
|
+
module ValidatesWithin
|
43
|
+
##
|
44
|
+
# Validates that the value of a field is within a range/set.
|
45
|
+
#
|
46
|
+
# This validation is defined by passing a field along with a :set
|
47
|
+
# parameter. The :set can be a Range or any object which responds
|
48
|
+
# to the #include? method (an array, for example).
|
49
|
+
#
|
50
|
+
# @example Usage
|
51
|
+
# require 'dm-validations'
|
52
|
+
#
|
53
|
+
# class Review
|
54
|
+
# include DataMapper::Resource
|
55
|
+
#
|
56
|
+
# STATES = ['new', 'in_progress', 'published', 'archived']
|
57
|
+
#
|
58
|
+
# property :title, String
|
59
|
+
# property :body, String
|
60
|
+
# property :review_state, String
|
61
|
+
# property :rating, Integer
|
62
|
+
#
|
63
|
+
# validates_within :review_state, :set => STATES
|
64
|
+
# validates_within :rating, :set => 1..5
|
65
|
+
#
|
66
|
+
# # a call to valid? will return false unless
|
67
|
+
# # the two properties conform to their sets
|
68
|
+
# end
|
69
|
+
def validates_within(*fields)
|
70
|
+
validators.add(WithinValidator, *fields)
|
71
|
+
end
|
72
|
+
end # module ValidatesWithin
|
73
|
+
end # module Validations
|
74
|
+
end # module DataMapper
|