lib/holidays/option/context/parse_options.rb
module Holidays module Option module Context class ParseOptions def initialize(regions_repo, region_validator, definition_merger) @regions_repo = regions_repo @region_validator = region_validator @definition_merger = definition_merger end # Returns [(arr)regions, (bool)observed, (bool)informal] def call(*options) options.flatten! #TODO This is garbage. These two deletes MUST come before the # parse_regions call, otherwise it thinks that :observed and :informal # are regions to parse. We should be splitting these things out. observed = options.delete(:observed) ? true : false informal = options.delete(:informal) ? true : false regions = parse_regions!(options) return regions, observed, informal end private attr_reader :regions_repo, :region_validator, :definition_merger # Check regions against list of supported regions and return an array of # symbols. # # If a wildcard region is found (e.g. :ca_) it is expanded into all # of its available sub regions. def parse_regions!(regions) regions = [regions] unless regions.kind_of?(Array) return [:any] if regions.empty? regions = regions.collect { |r| r.to_sym } validate!(regions) # Found sub region wild-card regions.delete_if do |r| if r.to_s =~ /_$/ load_containing_region(r.to_s) regions << regions_repo.search(r.to_s) true end end regions.flatten! load_definition_data("north_america") if regions.include?(:us) # special case for north_america/US cross-linking regions.each do |region| unless region == :any || regions_repo.exists?(region) begin load_definition_data(region.to_s) rescue NameError => e # This could be a sub region that does not have any holiday # definitions of its own; try to load the containing region instead. if region.to_s =~ /_/ load_containing_region(region.to_s) else raise UnknownRegionError.new(e), "Could not load #{region.to_s}" end end end end regions end def validate!(regions) regions.each do |r| raise UnknownRegionError unless region_validator.valid?(r) end end # Derive the containing region from a sub region wild-card or a sub region # and load its definition. (Common code factored out from parse_regions) def load_containing_region(sub_reg) prefix = sub_reg.split('_').first return if regions_repo.exists?(prefix.to_sym) begin load_definition_data(prefix) rescue NameError => e raise UnknownRegionError.new(e), "Could not load region prefix: #{prefix.to_s}, original subregion: #{sub_reg.to_s}" end end def load_definition_data(region) target_region_module = Module.const_get("Holidays").const_get(region.upcase) definition_merger.call( target_region_module.defined_regions, target_region_module.holidays_by_month, target_region_module.custom_methods, ) end end end end end