ardm-validations 1.2.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 +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
|