module Uncharted class Country def subdivisions @subdivisions ||= [] end def territories @territories ||= find_by_type(:territory) end def states @states ||= find_by_type(:state) end def districts @districts ||= find_by_type(:district) end def self.subdivisions Territory.data end def find_by_type(type) subdivisions.select {|t| t.type == type} end end class Territory attr_reader :abbr, :code, :country, :country_code, :type def initialize(code, type, name) @code = code @type = type @name = name @country_code, @abbr = code.split('-') @country = Country.find(@country_code) Territory.data[code] = self @country.subdivisions << self if @country end def name(options = {}) I18n.t("territories.#{@country_code}#{@abbr}", {locale: options[:locale] || I18n.locale}, default: @name) end def names @names ||= Country.split_name(@name) end def to_s @abbr end def self.find(object) territory = object && object.is_a?(Territory) ? object : data[object] end def self.data @data ||= {} end def self.find_by_name(name) closest = [nil, 0] @data.each do |code, territory| return territory if territory.name == name intersection = territory.names & Country.split_name(name) size = intersection.size return territory if size == territory.names.size closest = [territory, size] if closest.last < size end return closest.first end def self.search(object) find(object) || find_by_name(object) end end end