Class: WorldDb::StateTreeReader
- Inherits:
-
ReaderBaseWithMoreAttribs
- Object
- ReaderBaseWithMoreAttribs
- WorldDb::StateTreeReader
- Defined in:
- lib/worlddb/readers/state_tree.rb
Instance Method Summary collapse
Methods inherited from ReaderBaseWithMoreAttribs
from_file, from_string, from_zip, #initialize, #skip_tags?, #strict?
Methods included from TextUtils::ValueHelper
#is_state?, #match_city, #match_country, #match_metro, #match_metro_flag, #match_metro_pop, #match_state_for_country, #match_supra, #match_supra_flag
Constructor Details
This class inherits a constructor from WorldDb::ReaderBaseWithMoreAttribs
Instance Method Details
#read ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/worlddb/readers/state_tree.rb', line 7 def read ## for now requires country_id !! country = Country.find( @more_attribs[ :country_id ] ) puts "[StateTreeReader] country key: #{country.key}, name: #{country.name}" reader = TreeReader.from_string( @text ) stack = [] # note: last_level => stack.size; starts w/ 0 if country.key == 'de' ## use state (1) > part (2) > county (3) > muni (4) > city (5) state_level = 1 # Land part_level = 2 # Regierungsbezirk county_level = 3 # Landkreis, Kreisfreie Stadt muni_level = 4 # Gemeinde city_level = 5 # Stadt, Ort, etc. else ## use state (1) > county (2) > muni (3) > city (4) state_level = 1 part_level = -1 ## note: not in use (-1) county_level = 2 muni_level = 3 city_level = 4 end reader.each_line do |nodes| names = nodes.map { |item| "(#{item.level}) #{item.value}" } node = nodes.last puts " #{names.join( ' › ' )}:" puts " key: >#{node.key}<, level: >#{node.level}<, value: >#{node.value}<" ## use name for lookup - use where() to find - might match more than 1 record!! ## todo/fix: check for multiple or no matches!!! ## todo/fix: check how to add state.id scope (and country.id scope) etc. ## add state.id to name - why? why not? ## move finders to name model for reuse (and testing) - why? why not ?? if node.level == state_level # 1 ## was: rec = State.where( "name like '#{node.value}%'" ).first names = Name.joins( :place => :state ).find_by( :name => node.value, :place_kind => 'STAT', :'states.country_id' => country.id ) rec = if names.nil? nil else names.place.state # get first record; fix: use where instead of find_by etc. end elsif node.level == part_level # 2 state = stack[0] rec = Part.where( "name like '#{node.value}%' AND state_id = #{state.id}" ).first elsif node.level == county_level # 2 or 3 state = stack[0] ## was: rec = County.where( "name like '#{node.value}%' AND state_id = #{state.id}" ).first names = Name.joins( :place => :county ).find_by( :name => node.value, :place_kind => 'COUN', :'counties.state_id' => state.id ) rec = if names.nil? nil else names.place.county # get first record end elsif node.level == muni_level # 3 or 4 state = stack[0] ## was: rec = Muni.where( "name like '#{node.value}%' AND state_id = #{state.id}" ).first names = Name.joins( :place => :muni ).find_by( :name => node.value, :place_kind => 'MUNI', :'munis.state_id' => state.id ) rec = if names.nil? nil else names.place.muni # get first record end elsif node.level == city_level # 4 or 5 ## note: city requires country scope for lookup ## todo/fix: how to deal with cities with the same name ## in the same country (and same state and same county etc.) ??? - add some examples here rec = City.where( "name like '#{node.value}%' AND country_id = #{country.id}" ).first else puts "*** (fatal) error: unknown level for tree node: #{node.inspect}" ## todo/fix: exit here end if rec.present? puts "ok - record match found: #{rec.inspect}" else ## note: for now only auto-adds munis n cities if node.level == muni_level # 3 or 4 ## add muni key = TextUtils.title_to_key( node.value ) name = node.value level = node.level state = stack[0] county = stack[county_level-1] # note: stack is zero-based (thus, -1) puts "*** adding muni record:" rec = Muni.create!( key: key, name: name, level: level, state_id: state.id, county_id: county.id ) elsif node.level == city_level # 4 or 5 ## add city key = TextUtils.title_to_key( node.value ) name = node.value state = stack[0] county = stack[county_level-1] # note: stack is zero-based (thus, -1) muni = stack[muni_level-1] # note: stack is zero-based (thus, -1) puts "*** adding city record:" rec = City.create!( key: key, name: name, state_id: state.id, ## add county_id too ??? muni_id: muni.id, country_id: country.id ) else puts "*** (fatal) error: record not found for tree node: #{node.inspect}" ## todo/fix: exit here end end level_diff = node.level - stack.size if level_diff > 0 logger.debug "[StateTreeReader] up +#{level_diff}" ## FIX!!! todo/check/verify/assert: always must be +1 elsif level_diff < 0 logger.debug "[StateTreeReader] down #{level_diff}" level_diff.abs.times { stack.pop } stack.pop else ## same level stack.pop end stack.push( rec ) ## hierarchy of records (mirrors hierarchy of read-in text) end # each_line end |