validates_date_time.rb
来自「A Hotel Management System based on Ruby 」· RB 代码 · 共 102 行
RB
102 行
require File.dirname(__FILE__) + '/parser'
require File.dirname(__FILE__) + '/restrictions'
module ActiveRecord::Validations::DateTime
def self.included(base)
base.extend(ClassMethods)
base.send(:include, InstanceMethods)
end
mattr_accessor :us_date_format
us_date_format = false
module ClassMethods
%w{date time date_time}.each do |validator|
class_eval <<-END
def validates_#{validator}(*attr_names)
configuration = { :message => "is an invalid #{validator.humanize.downcase}",
:before_message => "must be before %s",
:after_message => "must be after %s",
:on => :save }
configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
configuration.assert_valid_keys :message, :before_message, :after_message, :before, :after, :if, :on, :allow_nil
# We must remove this from the configuration that is passed to validates_each because
# we want to have our own definition of nil that uses the before_type_cast value
allow_nil = configuration.delete(:allow_nil)
before_restrictions, after_restrictions = Restrictions.relative_#{validator}_restrictions(configuration)
validates_each(attr_names, configuration) do |record, attr_name, value|
value_to_parse = record.send("\#{attr_name}_before_type_cast")
if value_to_parse.blank? && allow_nil
record.send("\#{attr_name}=", nil)
else
value_to_parse = Parser.parse_date_time(value_to_parse) rescue value_to_parse
begin
result = Parser.parse_#{validator}(value_to_parse)
if failed_restriction = Restrictions.#{validator}_before(result, record, before_restrictions)
record.errors.add(attr_name, configuration[:before_message] % failed_restriction)
end
if failed_restriction = Restrictions.#{validator}_after(result, record, after_restrictions)
record.errors.add(attr_name, configuration[:after_message] % failed_restriction)
end
record.send("\#{attr_name}=", result) unless record.errors.on(attr_name)
rescue Parser::#{validator.camelize}ParseError
record.errors.add(attr_name, configuration[:message])
end
end
end
end
END
end
end
module InstanceMethods
def execute_callstack_for_multiparameter_attributes_with_temporal_error_handling(callstack)
errors = []
callstack.each do |name, values|
klass = (self.class.reflect_on_aggregation(name.to_sym) || column_for_attribute(name)).klass
if values.empty?
send("#{name}=", nil)
else
if [Date, Time].include?(klass)
values = values.map(&:to_s)
date_string = [values.shift.rjust(4, "0"), *values.slice!(0, 2).map { |s| s.rjust(2, "0") }].join('-')
if klass == Date
send("#{name}=", date_string)
elsif klass == Time
time_string = values.map { |s| s.rjust(2, "0") }.join(':')
send("#{name}=", "#{date_string} #{time_string}")
end
else
begin
send(name + "=", Time == klass ? klass.local(*values) : klass.new(*values))
rescue => ex
errors << ActiveRecord::AttributeAssignmentError.new("error on assignment #{values.inspect} to #{name}", ex, name)
end
end
end
end
unless errors.empty?
raise ActiveRecord::MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes"
end
end
end
end
class ActiveRecord::Base include ActiveRecord::Validations::DateTime
alias_method :execute_callstack_for_multiparameter_attributes_without_temporal_error_handling, :execute_callstack_for_multiparameter_attributes
alias_method :execute_callstack_for_multiparameter_attributes, :execute_callstack_for_multiparameter_attributes_with_temporal_error_handling
end
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?