class WorldDb::Model::Country

Country / Supra (e.g. European Union) / Territory (e.g. Puerto Rico) or Dependency (e.g. Dependent territory)

Private Class Methods

create_or_update_from_attribs( new_attributes, values, opts={} ) click to toggle source
# File lib/worlddb/models/country.rb, line 202
  def self.create_or_update_from_attribs( new_attributes, values, opts={} )

    ## opts e.g. :skip_tags true|false

    ## fix: add/configure logger for ActiveRecord!!!
    logger = LogKernel::Logger.root

      value_numbers     = []
      value_tag_keys    = []
      value_cities      = []

      ### check for "default" tags - that is, if present new_attributes[:tags] remove from hash
      value_tag_keys += find_tags_in_attribs!( new_attributes )


      new_attributes[ :c ] = true   # assume country type by default (use supra,depend to change)

      ## check for optional values
      values.each_with_index do |value,index|
        if match_supra_flag( value ) do |_|  # supra(national)
             new_attributes[ :c ] = false   # turn off default c|country flag; make it s|supra only
             new_attributes[ :s ] = true
             ## auto-add tag supra
             value_tag_keys << 'supra'
           end
        elsif match_supra( value ) do |country| # supra:
                new_attributes[ :country_id ] = country.id
              end
        elsif match_country( value ) do |country| # country:
                new_attributes[ :country_id ] = country.id
                new_attributes[ :c ] = false # turn off default c|country flag; make it d|depend only
                new_attributes[ :d ] = true
                ## auto-add tag supra
                value_tag_keys << 'territory'  # rename tag to dependency? why? why not?
              end
        elsif match_km_squared( value ) do |num|  # allow numbers like 453 km²
                value_numbers << num
              end
        elsif match_number( value ) do |num|  # numeric (nb: can use any _ or spaces inside digits e.g. 1_000_000 or 1 000 000)
                value_numbers << num
              end
        elsif value =~ /#{COUNTRY_CODE_PATTERN}/  ## three letter code
          new_attributes[ :code ] = value
        elsif (values.size==(index+1)) && is_taglist?( value )   # tags must be last entry
          logger.debug "   found tags: >>#{value}<<"
          value_tag_keys += find_tags( value )
        else

          ### assume it is the capital city - mark it for auto add
          value_cities << value
          next

          # issue warning: unknown type for value
          # logger.warn "unknown type for value >#{value}<"
        end
      end # each value

      if value_numbers.size > 0
          new_attributes[ :area ] = value_numbers[0]
          new_attributes[ :pop  ] = value_numbers[1]
      end

=begin
            # auto-add tags
            area = value_numbers[0]
            pop  = value_numbers[1]

            # categorize into brackets
            if area >= 1_000_000
              value_tag_keys << 'area_1_000_000_n_up'
            elsif area >= 100_000
              value_tag_keys << 'area_100_000_to_1_000_000'
            elsif area >= 1000
              value_tag_keys << 'area_1_000_to_100_000'
            else
              value_tag_keys << 'area_1_000_n_less' # microstate
            end

            # include all
            value_tag_keys << 'area_100_000_n_up'  if area >= 100_000
            value_tag_keys << 'area_1_000_n_up'    if area >=   1_000


            # categorize into brackets
            if pop >= 100_000_000
              value_tag_keys << 'pop_100m_n_up'
            elsif pop >= 10_000_000
              value_tag_keys << 'pop_10m_to_100m'
            elsif pop >= 1_000_000
              value_tag_keys << 'pop_1m_to_10m'
            else
              value_tag_keys << 'pop_1m_n_less'
            end

            # include all
            value_tag_keys << 'pop_10m_n_up'  if pop >= 10_000_000
            value_tag_keys << 'pop_1m_n_up'   if pop >=  1_000_000
=end


      rec = Country.find_by_key( new_attributes[ :key ] )

      if rec.present?
        logger.debug "update Country #{rec.id}-#{rec.key}:"
      else
        logger.debug "create Country:"
        rec = Country.new
      end

      logger.debug new_attributes.to_json

      rec.update_attributes!( new_attributes )

      #################
      ## auto add capital cities

      City.parse( value_cities, country_id: rec.id )

      ##################
      ## add taggings

      if value_tag_keys.size > 0

        if opts[:skip_tags].present?
          logger.debug "   skipping add taggings (flag skip_tag)"
        else
          value_tag_keys.uniq!  # remove duplicates
          logger.debug "   adding #{value_tag_keys.size} taggings: >>#{value_tag_keys.join('|')}<<..."

          ### fix/todo: check tag_ids and only update diff (add/remove ids)

          value_tag_keys.each do |key|
            tag = Tag.find_by_key( key )
            if tag.nil?  # create tag if it doesn't exit
              logger.debug "   creating tag >#{key}<"
              tag = Tag.create!( key: key )
            end
            rec.tags << tag
          end
        end
      end

    rec

  end
create_or_update_from_values( values, more_attribs={} ) click to toggle source
# File lib/worlddb/models/country.rb, line 191
def self.create_or_update_from_values( values, more_attribs={} )

    ## key & title
    ## NB: three-letter code (.e.g AUT) required - enforce in values? why? why not?
    attribs, more_values = find_key_n_title( values )
    attribs = attribs.merge( more_attribs )

    Country.create_or_update_from_attribs( attribs, more_values )
end
parse( *args ) click to toggle source
# File lib/worlddb/models/country.rb, line 183
def self.parse( *args )
  ## remove (extract) attribs hash (if last arg is a hash n present)
  more_attribs = args.last.is_a?(Hash) ? args.pop : {}  ## extract_options!
  values       = args

  self.create_or_update_from_values( values, more_attribs )
end
search_by_name( q ) click to toggle source
# File lib/worlddb/models/country.rb, line 138
def self.search_by_name( q )    ## todo/check: just use search (rename)? why? why not?

  ## fix: add/configure logger for ActiveRecord!!!
  ## logger = LogKernel::Logger.root

  name = q.strip

  ## 1) first try 1:1 (exact) match
  cty = Country.find_by_name( name )   # NOTE: assume AR escapes quotes in name ??
  if cty.nil?
    ## 2) retry: a) remove all (..) enclosed
    ##           b) remove all extra spaces (e.g. Cocos (Keeling) Islands => Cocos__Islands => Cocos_Islands)
    name = name.gsub( /\([^)]+\)/, '' ).strip
    name = name.gsub( /[ \t]{2,}/, ' ' )
    cty = Country.find_by_name( name )

    ### NOTE: escape ' for sql like clause
    ##   for now use '' for escapes, that is, double quotes
    ##  check - working for postgresql n sqlite??
    name_esc = name.gsub( /'/, "''" )

    ## 3) retry: use SQL like match
    ##    % is used to match *zero* or more occurrences of any characters
    ##  todo: check if it matches zero too
    if cty.nil?
      cty = Country.where( "name LIKE '%#{name_esc}%'" ).first
    end

    ## 4) retry: use SQL like match for alternative names match
    if cty.nil?
      cty = Country.where( "alt_names LIKE '%#{name_esc}%'" ).first
    end

    ## 5) retry: use SQL like match for historic names match (e.g. Burma for Myanmar etc.)
    ##  todo/check: make it optional (pass in opts hash to configure) - why? why not???
    if cty.nil?
      cty = Country.where( "hist_names LIKE '%#{name_esc}%'" ).first
    end
  end

  cty  # return cty (country); nil if not found
end

Private Instance Methods

all_names( opts={} ) click to toggle source
# File lib/worlddb/models/country.rb, line 118
def all_names( opts={} )
  ### fix:
  ## allow to passing in sep or separator e.g. | or other

  return name if alt_names.blank?

  buf = ''
  buf << name
  buf << ' | '
  buf << alt_names.split('|').join(' | ')
  buf
end
as_row( opts={} ) click to toggle source
# File lib/worlddb/models/country.rb, line 65
def as_row( opts={} )
  CountrySerializer.new( self ).as_row
end
is_country?() click to toggle source
# File lib/worlddb/models/country.rb, line 113
def is_country?()    c? == true;  end
is_dependency?() click to toggle source
# File lib/worlddb/models/country.rb, line 114
def is_dependency?() d? == true;  end
is_misc?() click to toggle source
# File lib/worlddb/models/country.rb, line 115
def is_misc?()       m? == true;  end
is_supra?() click to toggle source

NB: use is_ for flags to avoid conflict w/ assocs

# File lib/worlddb/models/country.rb, line 112
def is_supra?()      s? == true;  end
on_create() click to toggle source
# File lib/worlddb/models/country.rb, line 73
def on_create
  place_rec = Place.create!( name: name, kind: place_kind )
  self.place_id = place_rec.id

  if slug.blank?
    ## todo: change and to n  (if en/english) ?? - why? why not?
    ##  remove subtitles/subnames e.g. () -- why? why not?

    ## remove translations []  e.g. México [Mexico] -> México etc.
    self.slug = TextUtils.slugify( name.gsub( /\[[^\]]+\]/, '' ) )
  end
end
on_update() click to toggle source
# File lib/worlddb/models/country.rb, line 86
def on_update
  ## fix/todo: check - if name or kind changed - only update if changed ?? why? why not??
  place.update_attributes!( name: name, kind: place_kind )

  ## check if name changed -- possible?
  ## update slug too??
end
place_kind() click to toggle source
# File lib/worlddb/models/country.rb, line 94
def place_kind   # use place_kind_of_code ??
  if is_supra?
    'SUPR'
  elsif is_dependency?
    'TERR'
  elsif is_misc?  ## misc(ellaneous) country or dependent territory
    # todo: use different marker?
    # territory w/ shared or disputes claims e.g Antartica/Western Sahara/Paracel Islands pg Spratly Islands/etc.
    'MISC'
  else
    'CNTY'
  end
end
synonyms() click to toggle source
# File lib/worlddb/models/country.rb, line 45
def synonyms()       alt_names;              end
synonyms=(value) click to toggle source
# File lib/worlddb/models/country.rb, line 46
def synonyms=(value) self.alt_names = value; end
title() click to toggle source

begin compat

# File lib/worlddb/models/country.rb, line 42
def title()       name;              end
title=(value) click to toggle source
# File lib/worlddb/models/country.rb, line 43
def title=(value) self.name = value; end
to_path( opts={} ) click to toggle source
# File lib/worlddb/models/country.rb, line 132
def to_path( opts={} )
  # e.g. europe/at-austria
  "#{continent.slug}/#{key}-#{slug}"
end