datamapper 0.2.3 → 0.2.4
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/example.rb +5 -5
- data/lib/data_mapper/adapters/abstract_adapter.rb +2 -2
- data/lib/data_mapper/adapters/data_object_adapter.rb +141 -147
- data/lib/data_mapper/adapters/mysql_adapter.rb +14 -1
- data/lib/data_mapper/adapters/postgresql_adapter.rb +123 -18
- data/lib/data_mapper/adapters/sql/coersion.rb +21 -9
- data/lib/data_mapper/adapters/sql/commands/load_command.rb +36 -19
- data/lib/data_mapper/adapters/sql/mappings/column.rb +111 -17
- data/lib/data_mapper/adapters/sql/mappings/schema.rb +27 -0
- data/lib/data_mapper/adapters/sql/mappings/table.rb +256 -29
- data/lib/data_mapper/adapters/sqlite3_adapter.rb +93 -8
- data/lib/data_mapper/associations/belongs_to_association.rb +53 -54
- data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +157 -25
- data/lib/data_mapper/associations/has_many_association.rb +45 -15
- data/lib/data_mapper/associations/has_n_association.rb +79 -20
- data/lib/data_mapper/associations/has_one_association.rb +2 -2
- data/lib/data_mapper/associations/reference.rb +1 -1
- data/lib/data_mapper/auto_migrations.rb +40 -0
- data/lib/data_mapper/base.rb +201 -98
- data/lib/data_mapper/context.rb +16 -10
- data/lib/data_mapper/database.rb +22 -11
- data/lib/data_mapper/dependency_queue.rb +28 -0
- data/lib/data_mapper/embedded_value.rb +61 -17
- data/lib/data_mapper/property.rb +4 -0
- data/lib/data_mapper/support/active_record_impersonation.rb +13 -5
- data/lib/data_mapper/support/errors.rb +5 -0
- data/lib/data_mapper/support/serialization.rb +8 -4
- data/lib/data_mapper/validatable_extensions/errors.rb +12 -0
- data/lib/data_mapper/validatable_extensions/macros.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validatable_instance_methods.rb +62 -0
- data/lib/data_mapper/validatable_extensions/validation_base.rb +18 -0
- data/lib/data_mapper/validatable_extensions/validations/formats/email.rb +43 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_acceptance_of.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_confirmation_of.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_each.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_format_of.rb +28 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_length_of.rb +15 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_numericality_of.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_presence_of.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_true_for.rb +7 -0
- data/lib/data_mapper/validatable_extensions/validations/validates_uniqueness_of.rb +33 -0
- data/lib/data_mapper/validations.rb +20 -0
- data/lib/data_mapper.rb +39 -34
- data/performance.rb +24 -18
- data/plugins/dataobjects/do_rb +0 -0
- data/rakefile.rb +12 -2
- data/spec/active_record_impersonation_spec.rb +133 -0
- data/spec/acts_as_tree_spec.rb +25 -9
- data/spec/associations_spec.rb +124 -4
- data/spec/attributes_spec.rb +13 -0
- data/spec/auto_migrations_spec.rb +44 -0
- data/spec/base_spec.rb +189 -1
- data/spec/column_spec.rb +85 -7
- data/spec/conditions_spec.rb +2 -2
- data/spec/dependency_spec.rb +25 -0
- data/spec/embedded_value_spec.rb +123 -3
- data/spec/fixtures/animals.yaml +1 -0
- data/spec/fixtures/careers.yaml +5 -0
- data/spec/fixtures/comments.yaml +1 -0
- data/spec/fixtures/people.yaml +14 -9
- data/spec/fixtures/projects.yaml +4 -0
- data/spec/fixtures/sections.yaml +5 -0
- data/spec/fixtures/serializers.yaml +6 -0
- data/spec/fixtures/users.yaml +1 -0
- data/spec/load_command_spec.rb +5 -4
- data/spec/mock_adapter.rb +2 -2
- data/spec/models/animal.rb +2 -1
- data/spec/models/animals_exhibit.rb +2 -2
- data/spec/models/career.rb +6 -0
- data/spec/models/comment.rb +4 -0
- data/spec/models/exhibit.rb +4 -0
- data/spec/models/person.rb +3 -13
- data/spec/models/project.rb +1 -1
- data/spec/models/serializer.rb +3 -0
- data/spec/models/user.rb +4 -0
- data/spec/models/zoo.rb +8 -1
- data/spec/natural_key_spec.rb +36 -0
- data/spec/paranoia_spec.rb +36 -0
- data/spec/property_spec.rb +70 -0
- data/spec/schema_spec.rb +10 -2
- data/spec/serialization_spec.rb +6 -3
- data/spec/serialize_spec.rb +19 -0
- data/spec/single_table_inheritance_spec.rb +7 -1
- data/spec/spec_helper.rb +26 -8
- data/spec/table_spec.rb +33 -0
- data/spec/validates_confirmation_of_spec.rb +20 -4
- data/spec/validates_format_of_spec.rb +22 -8
- data/spec/validates_length_of_spec.rb +26 -13
- data/spec/validates_uniqueness_of_spec.rb +18 -5
- data/spec/validations_spec.rb +55 -10
- data/tasks/fixtures.rb +13 -7
- metadata +189 -153
- data/lib/data_mapper/validations/confirmation_validator.rb +0 -53
- data/lib/data_mapper/validations/contextual_validations.rb +0 -50
- data/lib/data_mapper/validations/format_validator.rb +0 -85
- data/lib/data_mapper/validations/formats/email.rb +0 -78
- data/lib/data_mapper/validations/generic_validator.rb +0 -22
- data/lib/data_mapper/validations/length_validator.rb +0 -76
- data/lib/data_mapper/validations/required_field_validator.rb +0 -41
- data/lib/data_mapper/validations/unique_validator.rb +0 -56
- data/lib/data_mapper/validations/validation_errors.rb +0 -37
- data/lib/data_mapper/validations/validation_helper.rb +0 -77
- data/plugins/dataobjects/REVISION +0 -1
- data/plugins/dataobjects/Rakefile +0 -9
- data/plugins/dataobjects/do.rb +0 -348
- data/plugins/dataobjects/do_mysql.rb +0 -212
- data/plugins/dataobjects/do_postgres.rb +0 -196
- data/plugins/dataobjects/do_sqlite3.rb +0 -157
- data/plugins/dataobjects/spec/do_spec.rb +0 -150
- data/plugins/dataobjects/spec/spec_helper.rb +0 -81
- data/plugins/dataobjects/swig_mysql/extconf.rb +0 -45
- data/plugins/dataobjects/swig_mysql/mysql_c.c +0 -16602
- data/plugins/dataobjects/swig_mysql/mysql_c.i +0 -67
- data/plugins/dataobjects/swig_mysql/mysql_supp.i +0 -46
- data/plugins/dataobjects/swig_postgres/extconf.rb +0 -29
- data/plugins/dataobjects/swig_postgres/postgres_c.c +0 -8185
- data/plugins/dataobjects/swig_postgres/postgres_c.i +0 -73
- data/plugins/dataobjects/swig_sqlite/extconf.rb +0 -9
- data/plugins/dataobjects/swig_sqlite/sqlite3_c.c +0 -4725
- data/plugins/dataobjects/swig_sqlite/sqlite_c.i +0 -168
- data/tasks/drivers.rb +0 -20
@@ -1,50 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
|
3
|
-
class ContextualValidations
|
4
|
-
|
5
|
-
# This will be raised when you try to access
|
6
|
-
# a context that's not a member of the DEFAULT_CONTEXTS array.
|
7
|
-
class UnknownContextError < StandardError
|
8
|
-
end
|
9
|
-
|
10
|
-
# Add your custom contexts here.
|
11
|
-
DEFAULT_CONTEXTS = [
|
12
|
-
:general, :create, :save, :update
|
13
|
-
]
|
14
|
-
|
15
|
-
def initialize
|
16
|
-
@contexts = Hash.new { |h,k| h[k.to_sym] = [] }
|
17
|
-
end
|
18
|
-
|
19
|
-
# Retrieves a context by symbol.
|
20
|
-
# Raises an exception if the symbol isn't a member of DEFAULT_CONTEXTS.
|
21
|
-
# This isn't to keep you from adding your own contexts, it's just to
|
22
|
-
# prevent errors due to typos. When adding your own contexts just
|
23
|
-
# remember to add it to DEFAULT_CONTEXTS first.
|
24
|
-
def context(name)
|
25
|
-
raise UnknownContextError.new(name) unless DEFAULT_CONTEXTS.include?(name)
|
26
|
-
@contexts[name]
|
27
|
-
end
|
28
|
-
|
29
|
-
# Clear out all the currently defined validators.
|
30
|
-
# This makes testing easier.
|
31
|
-
def clear!
|
32
|
-
@contexts.clear
|
33
|
-
end
|
34
|
-
|
35
|
-
# Execute all validations against an instance for a specified context,
|
36
|
-
# including the "always-on" :general context.
|
37
|
-
def execute(context_name, target)
|
38
|
-
target.errors.clear!
|
39
|
-
|
40
|
-
validations = context(context_name)
|
41
|
-
validations += context(:general) unless context_name == :general
|
42
|
-
|
43
|
-
validations.inject(true) do |result, validator|
|
44
|
-
result & validator.call(target)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
@@ -1,85 +0,0 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/formats/email'
|
2
|
-
|
3
|
-
module DataMapper
|
4
|
-
module Validations
|
5
|
-
|
6
|
-
class FormatValidator < GenericValidator
|
7
|
-
|
8
|
-
# Seems to me that all this email garbage belongs somewhere else... Where's the best
|
9
|
-
# place to stick it?
|
10
|
-
include DataMapper::Validations::Helpers::Email
|
11
|
-
|
12
|
-
FORMATS = {
|
13
|
-
:email_address => [lambda { |email_address| email_address =~ DataMapper::Validations::Helpers::Email::RFC2822::EmailAddress }, :invalid_email]
|
14
|
-
}
|
15
|
-
|
16
|
-
def initialize(field_name, options = {}, &b)
|
17
|
-
@field_name, @options = field_name, options
|
18
|
-
end
|
19
|
-
|
20
|
-
def call(target)
|
21
|
-
field_value = target.instance_variable_get("@#{@field_name}")
|
22
|
-
return true if @options[:allow_nil] && field_value.nil?
|
23
|
-
|
24
|
-
validation = (@options[:as] || @options[:with])
|
25
|
-
message_key = :invalid
|
26
|
-
|
27
|
-
# Figure out what to use as the actual validator. If a symbol is passed to :as, look up
|
28
|
-
# the canned validation in FORMATS.
|
29
|
-
validator = if validation.is_a? Symbol
|
30
|
-
if FORMATS[validation].is_a? Array
|
31
|
-
message_key = FORMATS[validation][1] || :invalid
|
32
|
-
FORMATS[validation][0]
|
33
|
-
else
|
34
|
-
FORMATS[validation] || validation
|
35
|
-
end
|
36
|
-
else
|
37
|
-
validation
|
38
|
-
end
|
39
|
-
|
40
|
-
valid = case validator
|
41
|
-
when Proc then validator.call(field_value)
|
42
|
-
when Regexp then validator =~ field_value
|
43
|
-
else raise UnknownValidationFormat, "Can't determine how to validate #{target.class}##{@field_name} with #{validator.inspect}"
|
44
|
-
end
|
45
|
-
|
46
|
-
unless valid
|
47
|
-
field = Inflector.humanize(@field_name)
|
48
|
-
value = target.instance_variable_get("@#{@field_name}")
|
49
|
-
|
50
|
-
error_message = if message_key == :invalid
|
51
|
-
'%s is invalid'.t(field)
|
52
|
-
else
|
53
|
-
'%s is not a valid email address'.t(value)
|
54
|
-
end
|
55
|
-
|
56
|
-
add_error(target, error_message , @field_name)
|
57
|
-
end
|
58
|
-
|
59
|
-
return valid
|
60
|
-
end
|
61
|
-
|
62
|
-
class UnknownValidationFormat < StandardError
|
63
|
-
end
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
module ValidatesFormatOf
|
68
|
-
def self.included(base)
|
69
|
-
base.extend(ClassMethods)
|
70
|
-
end
|
71
|
-
|
72
|
-
module ClassMethods
|
73
|
-
# No bueno?
|
74
|
-
DEFAULT_OPTIONS = { :on => :save }
|
75
|
-
|
76
|
-
def validates_format_of(field, options = {})
|
77
|
-
opts = retrieve_options_from_arguments_for_validators([options], DEFAULT_OPTIONS)
|
78
|
-
validations.context(opts[:context]) << Validations::FormatValidator.new(field, opts)
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
# http://www.faqs.org/rfcs/rfc2822.html
|
2
|
-
module DataMapper
|
3
|
-
module Validations
|
4
|
-
module Helpers
|
5
|
-
module Email
|
6
|
-
|
7
|
-
module RFC2822
|
8
|
-
EmailAddress = begin
|
9
|
-
alpha = "a-zA-Z"
|
10
|
-
digit = "0-9"
|
11
|
-
atext = "[#{alpha}#{digit}\!\#\$\%\&\'\*+\/\=\?\^\_\`\{\|\}\~\-]"
|
12
|
-
dot_atom_text = "#{atext}+([.]#{atext}*)*"
|
13
|
-
dot_atom = "#{dot_atom_text}"
|
14
|
-
qtext = '[^\\x0d\\x22\\x5c\\x80-\\xff]'
|
15
|
-
text = "[\\x01-\\x09\\x11\\x12\\x14-\\x7f]"
|
16
|
-
quoted_pair = "(\\x5c#{text})"
|
17
|
-
qcontent = "(?:#{qtext}|#{quoted_pair})"
|
18
|
-
quoted_string = "[\"]#{qcontent}+[\"]"
|
19
|
-
atom = "#{atext}+"
|
20
|
-
word = "(?:#{atom}|#{quoted_string})"
|
21
|
-
obs_local_part = "#{word}([.]#{word})*"
|
22
|
-
local_part = "(?:#{dot_atom}|#{quoted_string}|#{obs_local_part})"
|
23
|
-
no_ws_ctl = "\\x01-\\x08\\x11\\x12\\x14-\\x1f\\x7f"
|
24
|
-
dtext = "[#{no_ws_ctl}\\x21-\\x5a\\x5e-\\x7e]"
|
25
|
-
dcontent = "(?:#{dtext}|#{quoted_pair})"
|
26
|
-
domain_literal = "\\[#{dcontent}+\\]"
|
27
|
-
obs_domain = "#{atom}([.]#{atom})*"
|
28
|
-
domain = "(?:#{dot_atom}|#{domain_literal}|#{obs_domain})"
|
29
|
-
addr_spec = "#{local_part}\@#{domain}"
|
30
|
-
pattern = /^#{addr_spec}$/
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
=begin
|
40
|
-
addresses = [
|
41
|
-
'-- dave --@example.com', # (spaces are invalid unless enclosed in quotation marks)
|
42
|
-
'[dave]@example.com', # (square brackets are invalid, unless contained within quotation marks)
|
43
|
-
'.dave@example.com', # (the local part of a domain name cannot start with a period)
|
44
|
-
'Max@Job 3:14',
|
45
|
-
'Job@Book of Job',
|
46
|
-
'J. P. \'s-Gravezande, a.k.a. The Hacker!@example.com',
|
47
|
-
]
|
48
|
-
addresses.each do |address|
|
49
|
-
if address =~ RFC2822::EmailAddress
|
50
|
-
puts "#{address} deveria ter sido rejeitado, ERRO"
|
51
|
-
else
|
52
|
-
puts "#{address} rejeitado, OK"
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
addresses = [
|
58
|
-
'+1~1+@example.com',
|
59
|
-
'{_dave_}@example.com',
|
60
|
-
'"[[ dave ]]"@example.com',
|
61
|
-
'dave."dave"@example.com',
|
62
|
-
'test@localhost',
|
63
|
-
'test@example.com',
|
64
|
-
'test@example.co.uk',
|
65
|
-
'test@example.com.br',
|
66
|
-
'"J. P. \'s-Gravezande, a.k.a. The Hacker!"@example.com',
|
67
|
-
'me@[187.223.45.119]',
|
68
|
-
'someone@123.com',
|
69
|
-
'simon&garfunkel@songs.com'
|
70
|
-
]
|
71
|
-
addresses.each do |address|
|
72
|
-
if address =~ RFC2822::EmailAddress
|
73
|
-
puts "#{address} aceito, OK"
|
74
|
-
else
|
75
|
-
puts "#{address} deveria ser aceito, ERRO"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
=end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Validations
|
3
|
-
|
4
|
-
# All Validators should inherit from the GenericValidator.
|
5
|
-
class GenericValidator
|
6
|
-
|
7
|
-
# Adds an error message to the target class.
|
8
|
-
def add_error(target, message, attribute = :base)
|
9
|
-
target.errors.add(attribute, message)
|
10
|
-
end
|
11
|
-
|
12
|
-
# Call the validator. We use "call" so the operation
|
13
|
-
# is BoundMethod and Block compatible.
|
14
|
-
# The result should always be TRUE or FALSE.
|
15
|
-
def call(target)
|
16
|
-
raise 'You must overwrite this method'
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
22
|
-
end
|
@@ -1,76 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Validations
|
3
|
-
|
4
|
-
class LengthValidator < GenericValidator
|
5
|
-
|
6
|
-
def initialize(field_name, options)
|
7
|
-
@field_name = field_name
|
8
|
-
@options = options
|
9
|
-
|
10
|
-
@min = options[:minimum] || options[:min]
|
11
|
-
@max = options[:maximum] || options[:max]
|
12
|
-
@equal = options[:is] || options[:equals]
|
13
|
-
@range = options[:within] || options[:in]
|
14
|
-
|
15
|
-
@validation_method ||= :range if @range
|
16
|
-
@validation_method ||= :min if @min && @max.nil?
|
17
|
-
@validation_method ||= :max if @max && @min.nil?
|
18
|
-
@validation_method ||= :equals unless @equal.nil?
|
19
|
-
end
|
20
|
-
|
21
|
-
def call(target)
|
22
|
-
field_value = target.instance_variable_get("@#{@field_name}").to_s
|
23
|
-
return true if @options[:allow_nil] && field_value.nil?
|
24
|
-
|
25
|
-
# HACK seems hacky to do this on every validation, probably should do this elsewhere?
|
26
|
-
field = Inflector.humanize(@field_name)
|
27
|
-
min = @range ? @range.min : @min
|
28
|
-
max = @range ? @range.max : @max
|
29
|
-
equal = @equal
|
30
|
-
|
31
|
-
error_message = nil
|
32
|
-
|
33
|
-
case @validation_method
|
34
|
-
when :range then
|
35
|
-
unless valid = @range.include?(field_value.size)
|
36
|
-
error_message = '%s must be between %s and %s characters long'.t(field, min, max)
|
37
|
-
end
|
38
|
-
when :min then
|
39
|
-
unless valid = field_value.size >= min
|
40
|
-
error_message = '%s must be more than %s characters long'.t(field, min)
|
41
|
-
end
|
42
|
-
when :max then
|
43
|
-
unless valid = field_value.size <= max
|
44
|
-
error_message = '%s must be less than %s characters long'.t(field, max)
|
45
|
-
end
|
46
|
-
when :equals then
|
47
|
-
unless valid = field_value.size == equal
|
48
|
-
error_message = '%s must be %s characters long'.t(field, equal)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
add_error(target, error_message, @field_name) unless valid
|
53
|
-
|
54
|
-
return valid
|
55
|
-
end
|
56
|
-
|
57
|
-
end
|
58
|
-
|
59
|
-
module ValidatesLengthOf
|
60
|
-
def self.included(base)
|
61
|
-
base.extend(ClassMethods)
|
62
|
-
end
|
63
|
-
|
64
|
-
module ClassMethods
|
65
|
-
DEFAULT_VALIDATES_LENGTH_OF_OPTIONS = { :on => :save }
|
66
|
-
|
67
|
-
def validates_length_of(field, options = {})
|
68
|
-
opts = retrieve_options_from_arguments_for_validators([options], DEFAULT_VALIDATES_LENGTH_OF_OPTIONS)
|
69
|
-
validations.context(opts[:context]) << Validations::LengthValidator.new(field, opts)
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|
76
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Validations
|
3
|
-
|
4
|
-
class RequiredFieldValidator < GenericValidator
|
5
|
-
|
6
|
-
def initialize(field_name)
|
7
|
-
@field_name = field_name
|
8
|
-
end
|
9
|
-
|
10
|
-
def call(target)
|
11
|
-
field_value = !target.instance_variable_get("@#{@field_name}").nil?
|
12
|
-
return true if field_value
|
13
|
-
|
14
|
-
error_message = "%s must not be blank".t(Inflector.humanize(@field_name))
|
15
|
-
add_error(target, error_message , @field_name)
|
16
|
-
|
17
|
-
return false
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
module ValidatesPresenceOf
|
23
|
-
def self.included(base)
|
24
|
-
base.extend(ClassMethods)
|
25
|
-
end
|
26
|
-
|
27
|
-
module ClassMethods
|
28
|
-
|
29
|
-
def validates_presence_of(*fields)
|
30
|
-
options = retrieve_options_from_arguments_for_validators(fields)
|
31
|
-
|
32
|
-
fields.each do |field|
|
33
|
-
validations.context(options[:context]) << Validations::RequiredFieldValidator.new(field)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
module Validations
|
3
|
-
|
4
|
-
class UniqueValidator < GenericValidator
|
5
|
-
|
6
|
-
def initialize(field_name, options = {})
|
7
|
-
@options = options
|
8
|
-
@field_name = field_name.to_sym
|
9
|
-
end
|
10
|
-
|
11
|
-
def call(target)
|
12
|
-
unless valid?(target)
|
13
|
-
error_message = '%s has already been taken'.t(Inflector.humanize(@field_name))
|
14
|
-
add_error(target, error_message , @field_name)
|
15
|
-
return false
|
16
|
-
end
|
17
|
-
|
18
|
-
return true
|
19
|
-
end
|
20
|
-
|
21
|
-
def valid?(target)
|
22
|
-
field_value = target.instance_variable_get("@#{@field_name}")
|
23
|
-
return true if @options[:allow_nil] && field_value.nil?
|
24
|
-
|
25
|
-
finder_options = { @field_name => field_value }
|
26
|
-
|
27
|
-
if @options[:scope]
|
28
|
-
scope_value = target.instance_variable_get("@#{@options[:scope]}")
|
29
|
-
finder_options.merge! @options[:scope] => scope_value
|
30
|
-
end
|
31
|
-
|
32
|
-
finder_options.merge!({ target.session.table(target.class).key.name.not => target.key }) unless target.new_record?
|
33
|
-
target.session.first(target.class, finder_options).nil?
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
module ValidatesUniquenessOf
|
39
|
-
def self.included(base)
|
40
|
-
base.extend(ClassMethods)
|
41
|
-
end
|
42
|
-
|
43
|
-
module ClassMethods
|
44
|
-
# No bueno?
|
45
|
-
DEFAULT_OPTIONS = { :on => :save }
|
46
|
-
|
47
|
-
def validates_uniqueness_of(field, options = {})
|
48
|
-
opts = retrieve_options_from_arguments_for_validators([options], DEFAULT_OPTIONS)
|
49
|
-
validations.context(opts[:context]) << Validations::UniqueValidator.new(field, opts)
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module DataMapper
|
2
|
-
|
3
|
-
class ValidationErrors
|
4
|
-
|
5
|
-
def initialize
|
6
|
-
@errors = Hash.new { |h,k| h[k.to_sym] = [] }
|
7
|
-
end
|
8
|
-
|
9
|
-
# Clear existing validation errors.
|
10
|
-
def clear!
|
11
|
-
@errors.clear
|
12
|
-
end
|
13
|
-
|
14
|
-
# Add a validation error. Use the attribute :general if
|
15
|
-
# the error doesn't apply to a specific attribute.
|
16
|
-
def add(attribute, message)
|
17
|
-
@errors[attribute] << message
|
18
|
-
end
|
19
|
-
|
20
|
-
# Collect all errors into a single list.
|
21
|
-
def full_messages
|
22
|
-
@errors.inject([]) do |list,pair|
|
23
|
-
list += pair.last
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def on(attribute)
|
28
|
-
@errors[attribute]
|
29
|
-
end
|
30
|
-
|
31
|
-
def method_missing(meth, *args)
|
32
|
-
@errors.send(meth, *args)
|
33
|
-
end
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
dirname = File.dirname(__FILE__)
|
2
|
-
|
3
|
-
require dirname + '/validation_errors'
|
4
|
-
require dirname + '/contextual_validations'
|
5
|
-
require dirname + '/generic_validator'
|
6
|
-
|
7
|
-
Dir[dirname + '/*_validator.rb'].reject do |path|
|
8
|
-
path =~ /\/generic_validator/
|
9
|
-
end.each do |validator|
|
10
|
-
load validator
|
11
|
-
end
|
12
|
-
|
13
|
-
module DataMapper
|
14
|
-
module Validations
|
15
|
-
|
16
|
-
module ValidationHelper
|
17
|
-
|
18
|
-
def self.included(base)
|
19
|
-
base.extend(ClassMethods)
|
20
|
-
base.class_eval do
|
21
|
-
include DataMapper::Validations::ValidatesPresenceOf
|
22
|
-
include DataMapper::Validations::ValidatesLengthOf
|
23
|
-
include DataMapper::Validations::ValidatesConfirmationOf
|
24
|
-
include DataMapper::Validations::ValidatesUniquenessOf
|
25
|
-
include DataMapper::Validations::ValidatesFormatOf
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def errors
|
30
|
-
@errors ||= ValidationErrors.new
|
31
|
-
end
|
32
|
-
|
33
|
-
def valid?(context = :general)
|
34
|
-
validate_excluding_association(nil, context)
|
35
|
-
end
|
36
|
-
|
37
|
-
def validate_excluding_association(associated, context = :general)
|
38
|
-
return false unless self.class.callbacks.execute(:before_validation, self)
|
39
|
-
return false unless self.class.validations.execute(context, self)
|
40
|
-
if self.respond_to?(:loaded_associations)
|
41
|
-
return false unless self.loaded_associations.all? do |association|
|
42
|
-
if association != associated && association.respond_to?(:validate_excluding_association)
|
43
|
-
association.validate_excluding_association(self, context)
|
44
|
-
else
|
45
|
-
true
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
return false unless self.class.callbacks.execute(:after_validation, self)
|
51
|
-
return true
|
52
|
-
end
|
53
|
-
|
54
|
-
module ClassMethods
|
55
|
-
|
56
|
-
def validations
|
57
|
-
@validations ||= ContextualValidations.new
|
58
|
-
end
|
59
|
-
|
60
|
-
def retrieve_options_from_arguments_for_validators(args, defaults = nil)
|
61
|
-
options = args.last.kind_of?(Hash) ? args.pop : {}
|
62
|
-
|
63
|
-
context = :general
|
64
|
-
context = options[:context] if options.has_key?(:context)
|
65
|
-
context = options.delete(:on) if options.has_key?(:on)
|
66
|
-
options[:context] = context
|
67
|
-
|
68
|
-
options.merge!(defaults) unless defaults.nil?
|
69
|
-
return options
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|
77
|
-
end
|
@@ -1 +0,0 @@
|
|
1
|
-
18
|