Created
May 5, 2009 14:41
-
-
Save mlins/106990 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module DateValidations | |
def self.included(base) # :nodoc: | |
base.extend ClassMethods | |
end | |
module ClassMethods | |
# Must pass a Proc object with a Range of Date, Time or DateTime. | |
# The Proc prevents the range from only being evaluated at initialization. | |
# All 'dates' are converted to Time objects for comparison sake. | |
def validates_date_range_of(*attr_names) | |
configuration = parse_configuration(attr_names) | |
check_for_valid_proc(configuration) | |
range = get_range(configuration) | |
validates_each(attr_names, configuration) do |record, attr_name, value| | |
if value.nil? || !range.include?(value.to_date) | |
record.errors.add(attr_name, error_message(configuration, range)) | |
end | |
end | |
end | |
protected | |
def parse_configuration(attr_names) | |
configuration = { :on => :save, :in => nil } | |
configuration.update(attr_names.extract_options!) | |
configuration | |
end | |
def check_for_valid_proc(configuration) | |
unless configuration[:in].is_a?(Proc) | |
raise(ArgumentError, "A Proc must be supplied as the :in option of the configuration hash") | |
end | |
unless configuration[:in].call.is_a?(Range) | |
raise(ArgumentError, "A Range must be returned from Proc.call of the :in option") | |
end | |
end | |
def get_range(configuration) | |
range = configuration[:in].call | |
[range.first, range.last].each do |date| | |
check_for_valid_range_date(date) | |
end | |
range.first.to_date..range.last.to_date | |
end | |
def check_for_valid_range_date(date) | |
[Date, DateTime, Time].each do |klass| | |
return if date.is_a?(klass) | |
end | |
raise(ArgumentError, "A Date, Time or DateTime object must be used to specify the Range.") | |
end | |
def error_message(configuration, range) | |
message = configuration[:message] | |
message ||= "must be between #{range.first.strftime("%m/%d/%Y")} " + | |
"and #{range.last.strftime("%m/%d/%Y")}" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment