621f5565e9
property :casted_attribute, :cast_as => 'WithCastedModelMixin' A casted attribute now knows about its parent. (#casted_by to retrieve the parent's object)
167 lines
6.1 KiB
Ruby
167 lines
6.1 KiB
Ruby
# Ported from dm-migrations
|
|
require File.join(File.dirname(__FILE__), '..', 'support', 'class')
|
|
|
|
module CouchRest
|
|
|
|
class Property
|
|
# flag letting us know if we already checked the autovalidation settings
|
|
attr_accessor :autovalidation_check
|
|
end
|
|
|
|
module Validation
|
|
module AutoValidate
|
|
|
|
# Turn off auto validation by default
|
|
def auto_validation
|
|
@@auto_validation ||= false
|
|
end
|
|
|
|
# Force the auto validation for the class properties
|
|
# This feature is still not fully ported over,
|
|
# test are lacking, so please use with caution
|
|
def auto_validate!
|
|
@@auto_validation = true
|
|
end
|
|
|
|
# adds message for validator
|
|
def options_with_message(base_options, property, validator_name)
|
|
options = base_options.clone
|
|
opts = property.options
|
|
options[:message] = if opts[:messages]
|
|
if opts[:messages].is_a?(Hash) and msg = opts[:messages][validator_name]
|
|
msg
|
|
else
|
|
nil
|
|
end
|
|
elsif opts[:message]
|
|
opts[:message]
|
|
else
|
|
nil
|
|
end
|
|
options
|
|
end
|
|
|
|
|
|
##
|
|
# Auto-generate validations for a given property. This will only occur
|
|
# if the option :auto_validation is either true or left undefined.
|
|
#
|
|
# @details [Triggers]
|
|
# Triggers that generate validator creation
|
|
#
|
|
# :nullable => false
|
|
# Setting the option :nullable to false causes a
|
|
# validates_presence_of validator to be automatically created on
|
|
# the property
|
|
#
|
|
# :size => 20 or :length => 20
|
|
# Setting the option :size or :length causes a validates_length_of
|
|
# validator to be automatically created on the property. If the
|
|
# value is a Integer the validation will set :maximum => value if
|
|
# the value is a Range the validation will set :within => value
|
|
#
|
|
# :format => :predefined / lambda / Proc
|
|
# Setting the :format option causes a validates_format_of
|
|
# validator to be automatically created on the property
|
|
#
|
|
# :set => ["foo", "bar", "baz"]
|
|
# Setting the :set option causes a validates_within
|
|
# validator to be automatically created on the property
|
|
#
|
|
# Integer type
|
|
# Using a Integer type causes a validates_is_number
|
|
# validator to be created for the property. integer_only
|
|
# is set to true
|
|
#
|
|
# BigDecimal or Float type
|
|
# Using a Integer type causes a validates_is_number
|
|
# validator to be created for the property. integer_only
|
|
# is set to false, and precision/scale match the property
|
|
#
|
|
#
|
|
# Messages
|
|
#
|
|
# :messages => {..}
|
|
# Setting :messages hash replaces standard error messages
|
|
# with custom ones. For instance:
|
|
# :messages => {:presence => "Field is required",
|
|
# :format => "Field has invalid format"}
|
|
# Hash keys are: :presence, :format, :length, :is_unique,
|
|
# :is_number, :is_primitive
|
|
#
|
|
# :message => "Some message"
|
|
# It is just shortcut if only one validation option is set
|
|
#
|
|
def auto_generate_validations(property)
|
|
return unless property.options
|
|
return unless property.autovalidation_check || auto_validation || (property.options && property.options.has_key?(:auto_validation) && property.options[:auto_validation])
|
|
|
|
# value is set by the storage system
|
|
opts = {}
|
|
opts[:context] = property.options[:validates] if property.options.has_key?(:validates)
|
|
|
|
# presence
|
|
unless opts[:allow_nil]
|
|
# validates_present property.name, opts
|
|
validates_present property.name, options_with_message(opts, property, :presence)
|
|
end
|
|
|
|
# length
|
|
if property.type == "String"
|
|
# XXX: maybe length should always return a Range, with the min defaulting to 1
|
|
# 52 being the max set
|
|
len = property.options.fetch(:length, property.options.fetch(:size, 52))
|
|
if len.is_a?(Range)
|
|
opts[:within] = len
|
|
else
|
|
opts[:maximum] = len
|
|
end
|
|
# validates_length property.name, opts
|
|
validates_length property.name, options_with_message(opts, property, :length)
|
|
end
|
|
|
|
# format
|
|
if property.options.has_key?(:format)
|
|
opts[:with] = property.options[:format]
|
|
# validates_format property.name, opts
|
|
validates_format property.name, options_with_message(opts, property, :format)
|
|
end
|
|
|
|
# uniqueness validator
|
|
if property.options.has_key?(:unique)
|
|
value = property.options[:unique]
|
|
if value.is_a?(Array) || value.is_a?(Symbol)
|
|
# validates_is_unique property.name, :scope => Array(value)
|
|
validates_is_unique property.name, options_with_message({:scope => Array(value)}, property, :is_unique)
|
|
elsif value.is_a?(TrueClass)
|
|
# validates_is_unique property.name
|
|
validates_is_unique property.name, options_with_message({}, property, :is_unique)
|
|
end
|
|
end
|
|
|
|
# within validator
|
|
if property.options.has_key?(:set)
|
|
validates_within property.name, options_with_message({:set => property.options[:set]}, property, :within)
|
|
end
|
|
|
|
# numeric validator
|
|
if "Integer" == property.type
|
|
opts[:integer_only] = true
|
|
# validates_is_number property.name, opts
|
|
validates_is_number property.name, options_with_message(opts, property, :is_number)
|
|
elsif Float == property.type
|
|
opts[:precision] = property.precision
|
|
opts[:scale] = property.scale
|
|
# validates_is_number property.name, opts
|
|
validates_is_number property.name, options_with_message(opts, property, :is_number)
|
|
end
|
|
|
|
# marked the property has checked
|
|
property.autovalidation_check = true
|
|
|
|
end
|
|
|
|
end # module AutoValidate
|
|
end # module Validation
|
|
end # module CouchRest
|