require "hiccup/convenience" require "active_support/concern" module Hiccup module Validatable include Convenience extend ActiveSupport::Concern # !todo: use ActiveModel:Validation rather than a custom method included do validate :validate_recurrence end private # !todo: use i18n to let clients of this library supply their own wording def validate_recurrence case kind when :never; when :weekly; validate_weekly_recurrence when :monthly; validate_monthly_recurrence when :annually; else; invalid_kind! end errors.add(:start_date, "is a #{self.start_date.class} not a Date") unless self.start_date.is_a?(Date) errors.add(:skip, "is not a positive integer") unless (skip.is_a? Fixnum) and (skip > 0) if ends? if self.end_date.is_a? Date errors.add(:end_date, "cannot be before start") if (self.end_date < self.start_date) else errors.add(:end_date, "is a #{self.end_date.class} not a Date") end end end def validate_weekly_recurrence if !weekly_pattern.is_a?(Array) errors.add(:weekly_pattern, "is a #{weekly_pattern.class}. It should be an array") elsif weekly_pattern.empty? errors.add(:weekly_pattern, "is empty. It should contain a list of weekdays") elsif (invalid_names = weekly_pattern - Date::DAYNAMES).any? errors.add(:weekly_pattern, "should contain only weekdays. (#{invalid_names.to_sentence} are invalid)") end end def validate_monthly_recurrence if !monthly_pattern.is_a?(Array) errors.add(:monthly_pattern, "is a #{monthly_pattern.class}. It should be an array") elsif monthly_pattern.empty? errors.add(:monthly_pattern, "is empty. It should contain a list of monthly occurrences") elsif monthly_pattern.select(&method(:invalid_occurrence?)).any? errors.add(:monthly_pattern, "contains invalid monthly occurrences") end end def invalid_occurrence?(occurrence) !valid_occurrence?(occurrence) end def valid_occurrence?(occurrence) if occurrence.is_a?(Array) i, wd = occurrence Date::DAYNAMES.member?(wd) && i.is_a?(Fixnum) && ((i == -1) || (1..6).include?(i)) else i = occurrence i.is_a?(Fixnum) && (1..31).include?(i) end end def invalid_kind! errors.add(:kind, "#{kind.inspect} is not recognized. It must be one of #{Kinds.collect{|kind| ":#{kind}"}.to_sentence(:two_words_connector => " or ", :last_word_connector => ", or ")}.") end # def valid_occurrence?(occurrence) # if occurrence.is_a?(Array) # ordinal, kind = occurrence # # errors.add(:kind, "is not a valid monthly occurrence kind") unless Date::DAYNAMES.member?(kind) # if ordinal.is_a?(Fixnum) # errors.add(:ordinal, "is not a valid integer") unless (ordinal==-1) or (1..6).include?(ordinal) # else # errors.add(:ordinal, "is not an integer") # end # else # ordinal = occurrence # # if ordinal.is_a?(Fixnum) # errors.add(:ordinal, "is not an integer between 1 and 31") unless (1..31).include?(ordinal) # else # errors.add(:ordinal, "is not an integer") # end # end # end end end