worlddb-models 2.2.2 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/Manifest.txt +31 -13
  3. data/README.md +7 -7
  4. data/Rakefile +1 -1
  5. data/lib/worlddb/deleter.rb +6 -1
  6. data/lib/worlddb/helpers/value_helper.rb +117 -0
  7. data/lib/worlddb/matcher.rb +99 -135
  8. data/lib/worlddb/matcher_adm.rb +82 -0
  9. data/lib/worlddb/models/city.rb +30 -208
  10. data/lib/worlddb/models/city_base.rb +220 -0
  11. data/lib/worlddb/models/continent.rb +9 -0
  12. data/lib/worlddb/models/country.rb +21 -4
  13. data/lib/worlddb/models/forward.rb +25 -9
  14. data/lib/worlddb/models/lang.rb +6 -0
  15. data/lib/worlddb/models/place.rb +1 -1
  16. data/lib/worlddb/models/state.rb +83 -0
  17. data/lib/worlddb/models/{region.rb → state_base.rb} +52 -36
  18. data/lib/worlddb/models/tagdb/tag.rb +1 -1
  19. data/lib/worlddb/models.rb +11 -8
  20. data/lib/worlddb/patterns.rb +4 -4
  21. data/lib/worlddb/reader.rb +68 -39
  22. data/lib/worlddb/reader_file.rb +36 -3
  23. data/lib/worlddb/reader_zip.rb +33 -3
  24. data/lib/worlddb/readers/base.rb +149 -0
  25. data/lib/worlddb/readers/city.rb +2 -65
  26. data/lib/worlddb/readers/country.rb +2 -63
  27. data/lib/worlddb/readers/lang.rb +3 -68
  28. data/lib/worlddb/readers/state.rb +61 -0
  29. data/lib/worlddb/readers/state_tree.rb +118 -0
  30. data/lib/worlddb/readers/usage.rb +2 -65
  31. data/lib/worlddb/schema.rb +142 -43
  32. data/lib/worlddb/stats.rb +7 -4
  33. data/lib/worlddb/tree_reader.rb +97 -0
  34. data/lib/worlddb/version.rb +2 -2
  35. data/test/adm/test_fixture_matcher_adm2.rb +73 -0
  36. data/test/{test_fixture_matcher_adm3.rb → adm/test_fixture_matcher_adm3.rb} +6 -6
  37. data/test/adm/test_fixture_matcher_tree.rb +52 -0
  38. data/test/{test_read_adm.rb → adm/test_read_adm.rb} +13 -20
  39. data/test/adm/test_read_tree.rb +63 -0
  40. data/test/data/at-austria/2--n-niederoesterreich/counties.txt +6 -4
  41. data/test/data/at-austria/orte.txt +23 -0
  42. data/test/data/at-austria/setups/tree.txt +9 -0
  43. data/test/data/de-deutschland/3--by-bayern/4--oberfranken/counties.txt +14 -13
  44. data/test/data/de-deutschland/3--by-bayern/4--oberfranken/orte.txt +104 -0
  45. data/test/data/de-deutschland/3--by-bayern/4--oberfranken/orte_ii.txt +17 -0
  46. data/test/data/de-deutschland/3--by-bayern/{districts.txt → parts.txt} +1 -1
  47. data/test/data/de-deutschland/orte.txt +12 -0
  48. data/test/data/de-deutschland/setups/adm.txt +1 -1
  49. data/test/data/de-deutschland/setups/tree.txt +9 -0
  50. data/test/helper.rb +8 -1
  51. data/test/test_fixture_matchers.rb +9 -10
  52. data/test/test_fixture_matchers_ii.rb +20 -19
  53. data/test/test_model_city.rb +26 -9
  54. data/test/{test_model_comp.rb → test_model_compat.rb} +15 -13
  55. data/test/test_model_country.rb +1 -1
  56. data/test/test_model_state.rb +54 -0
  57. data/test/test_model_states_at.rb +111 -0
  58. data/test/test_model_states_de.rb +147 -0
  59. data/test/test_models.rb +10 -3
  60. data/test/test_parse_city.rb +70 -0
  61. data/test/test_parse_country.rb +56 -0
  62. data/test/test_parse_state.rb +46 -0
  63. data/test/test_state_tree_reader_at.rb +54 -0
  64. data/test/test_state_tree_reader_de.rb +71 -0
  65. data/test/test_tree_reader.rb +39 -0
  66. metadata +50 -22
  67. data/lib/worlddb/models/city_compat.rb +0 -27
  68. data/lib/worlddb/models/continent_compat.rb +0 -24
  69. data/lib/worlddb/models/country_compat.rb +0 -35
  70. data/lib/worlddb/models/lang_compat.rb +0 -23
  71. data/lib/worlddb/models/region_compat.rb +0 -26
  72. data/lib/worlddb/readers/region.rb +0 -79
  73. data/test/test_fixture_matcher_adm2.rb +0 -62
  74. data/test/test_model_region.rb +0 -50
@@ -0,0 +1,83 @@
1
+ # encoding: UTF-8
2
+
3
+ module WorldDb
4
+ module Model
5
+
6
+
7
+ class State < StateBase
8
+
9
+ belongs_to :country, class_name: 'Country', foreign_key: 'country_id'
10
+
11
+ has_many :parts, class_name: 'Part', foreign_key: 'state_id' # x / ADM2
12
+ has_many :counties, class_name: 'County', foreign_key: 'state_id' # ADM2 / ADM3
13
+ has_many :munis, class_name: 'Muni', foreign_key: 'state_id' # ADM3 / ADM4
14
+ has_many :cities, class_name: 'City', foreign_key: 'state_id'
15
+
16
+ def place_kind # use place_kind_of_code ??
17
+ 'ADM1' # note: for now assumes always level 1
18
+ end
19
+
20
+ def state_id # return top-level (e.g. adm1) state_id
21
+ id
22
+ end
23
+
24
+ end # class State
25
+
26
+
27
+ class Part < StateBase ## optional ADM2 e.g. Regierungsbezirke in Bayern, etc.
28
+
29
+ belongs_to :state, class_name: 'State', foreign_key: 'state_id'
30
+
31
+ has_many :counties, class_name: 'County', foreign_key: 'part_id'
32
+ has_many :cities, class_name: 'City', foreign_key: 'part_id'
33
+
34
+ def place_kind # use place_kind_of_code ??
35
+ 'ADM2' # note: for now assumes always level 2
36
+ end
37
+
38
+ def country_id # return country_id via top-level (e.g. adm1) state; -- used for auto-creating cities
39
+ state.country_id
40
+ end
41
+
42
+ end # class Part
43
+
44
+
45
+ class County < StateBase ## note: might be ADM2 or ADM3
46
+
47
+ belongs_to :state, class_name: 'State', foreign_key: 'state_id'
48
+ belongs_to :part, class_name: 'Part', foreign_key: 'part_id' ## optional assoc (used if level=3 and not 2)
49
+
50
+ has_many :munis, class_name: 'Muni', foreign_key: 'county_id'
51
+ has_many :cities, class_name: 'City', foreign_key: 'county_id'
52
+
53
+ def place_kind # use place_kind_of_code ??
54
+ "ADM#{level}" # note: might be ADM2 or ADM3
55
+ end
56
+
57
+ def country_id # return country_id via top-level (e.g. adm1) state
58
+ state.country_id
59
+ end
60
+
61
+ end # class County
62
+
63
+
64
+ class Muni < StateBase ## note: might be ADM3 or ADM4
65
+
66
+ belongs_to :state, class_name: 'State', foreign_key: 'state_id'
67
+ belongs_to :county, class_name: 'County', foreign_key: 'county_id'
68
+
69
+ has_many :cities, class_name: 'City', foreign_key: 'muni_id'
70
+
71
+ def place_kind # use place_kind_of_code ??
72
+ "ADM#{level}" # note: might be ADM3 or ADM4
73
+ end
74
+
75
+ def country_id # return country_id via top-level (e.g. adm1) state
76
+ state.country_id
77
+ end
78
+
79
+ end # class Muni
80
+
81
+
82
+ end # module Model
83
+ end # module WorldDb
@@ -4,29 +4,35 @@ module WorldDb
4
4
  module Model
5
5
 
6
6
 
7
- class Region < ActiveRecord::Base
7
+ class StateBase < ActiveRecord::Base
8
+
9
+ self.abstract_class = true
8
10
 
9
11
  extend TextUtils::TagHelper # will add self.find_tags, self.find_tags_in_attribs!, etc.
10
12
 
11
13
  # NB: use extend - is_<type>? become class methods e.g. self.is_<type>? for use in
12
14
  # self.create_or_update_from_values
13
- extend TextUtils::ValueHelper # e.g. is_year?, is_region?, is_address?, is_taglist? etc.
15
+ extend TextUtils::ValueHelper # e.g. is_year?, is_address?, is_taglist? etc.
14
16
 
15
17
  belongs_to :place, class_name: 'Place', foreign_key: 'place_id'
16
- belongs_to :country, class_name: 'Country', foreign_key: 'country_id'
17
-
18
- has_many :cities, class_name: 'City', foreign_key: 'region_id'
19
18
 
20
- has_many_tags
19
+ has_many_tags # note: check if working w/ base class (statebase) -- use/try concern??
21
20
 
22
- validates :key, format: { with: /#{REGION_KEY_PATTERN}/, message: REGION_KEY_PATTERN_MESSAGE }
23
- validates :code, format: { with: /#{REGION_CODE_PATTERN}/, message: REGION_CODE_PATTERN_MESSAGE }, allow_nil: true
21
+ validates :key, format: { with: /#{STATE_KEY_PATTERN}/, message: STATE_KEY_PATTERN_MESSAGE }
22
+ validates :code, format: { with: /#{STATE_CODE_PATTERN}/, message: STATE_CODE_PATTERN_MESSAGE }, allow_nil: true
24
23
 
25
24
  ### recursive self-reference - use "generic" node??
26
- ## has_many :nodes, class_name: 'Region', foregin_key: 'region_id'
27
- belongs_to :parent, class_name: 'Region', foreign_key: 'region_id'
28
- has_many :regions, class_name: 'Region', foreign_key: 'region_id' ## subregions
25
+ ## has_many :nodes, class_name: 'State', foreign_key: 'state_id'
26
+ # belongs_to :parent, class_name: 'State', foreign_key: 'state_id'
27
+ # has_many :states, class_name: 'State', foreign_key: 'state_id' ## substates
29
28
 
29
+ ## begin compat
30
+ def title() name; end
31
+ def title=(value) self.name = value; end
32
+
33
+ def synonyms() alt_names; end
34
+ def synonyms=(value) self.alt_names = value; end
35
+ ## end
30
36
 
31
37
  before_create :on_create
32
38
  before_update :on_update
@@ -41,20 +47,6 @@ class Region < ActiveRecord::Base
41
47
  place.update_attributes!( name: name, kind: place_kind )
42
48
  end
43
49
 
44
- def is_district?() d? == true; end
45
- def is_county?() c? == true; end
46
-
47
- def place_kind # use place_kind_of_code ??
48
- ### fix: use "generic" level counter - make it a database field (default/top level is 1)
49
- if is_district?
50
- 'ADM2'
51
- elsif is_county?
52
- 'ADM3'
53
- else
54
- 'ADM1'
55
- end
56
- end
57
-
58
50
 
59
51
  def all_names( opts={} )
60
52
  ### fix:
@@ -70,15 +62,25 @@ class Region < ActiveRecord::Base
70
62
  end
71
63
 
72
64
 
65
+ def self.parse( *args )
66
+ ## remove (extract) attribs hash (if last arg is a hash n present)
67
+ more_attribs = args.last.is_a?(Hash) ? args.pop : {} ## extract_options!
68
+ values = args
69
+
70
+ self.create_or_update_from_values( values, more_attribs )
71
+ end
73
72
 
74
73
  def self.create_or_update_from_values( values, more_attribs={} )
75
74
 
76
75
  ## key & title & country required
77
76
  attribs, more_values = find_key_n_title( values )
77
+ ## fix/hack: change :title to :name
78
+ ## attribs[:name] = attribs[:title]; attribs.delete( :title )
78
79
  attribs = attribs.merge( more_attribs )
79
80
 
80
81
  ## check for optional values
81
- Region.create_or_update_from_attribs( attribs, more_values )
82
+ puts "[debug] StateBase.create_or_update_from_values calling #{self.name}" # note: assume self is derived class (object)
83
+ self.create_or_update_from_attribs( attribs, more_values )
82
84
  end
83
85
 
84
86
 
@@ -107,7 +109,7 @@ class Region < ActiveRecord::Base
107
109
  elsif match_number( value ) do |num| # numeric (nb: can use any _ or spaces inside digits e.g. 1_000_000 or 1 000 000)
108
110
  value_numbers << num
109
111
  end
110
- elsif value =~ /#{REGION_CODE_PATTERN}/ ## assume two or three-letter code
112
+ elsif value =~ /#{STATE_CODE_PATTERN}/ ## assume two or three-letter code
111
113
  new_attributes[ :code ] = value
112
114
  elsif (values.size==(index+1)) && is_taglist?( value ) # tags must be last entry
113
115
  logger.debug " found tags: >>#{value}<<"
@@ -129,27 +131,40 @@ class Region < ActiveRecord::Base
129
131
  end # if value_numbers.size > 0
130
132
 
131
133
  ## todo: assert that country_id is present/valid, that is, NOT null
132
- rec = Region.find_by_key_and_country_id( new_attributes[ :key ], new_attributes[ :country_id] )
134
+ puts "[debug] StateBase.create_or_update_from_attribs calling #{self.name}.where" # note: assume self is derived class (object)
135
+ # note: was self.find_by_key_and_country_id
136
+ if self == State
137
+ ## note: state scoped by country (all others by top-level state and NOT country)
138
+ rec = self.where(
139
+ key: new_attributes[ :key ],
140
+ country_id: new_attributes[ :country_id] ).first
141
+ else
142
+ rec = self.where(
143
+ key: new_attributes[ :key ],
144
+ state_id: new_attributes[ :state_id] ).first
145
+ end
133
146
 
134
147
  if rec.present?
135
- logger.debug "update Region #{rec.id}-#{rec.key}:"
148
+ logger.debug "update #{self.name} #{rec.id}-#{rec.key}:"
136
149
  else
137
- logger.debug "create Region:"
138
- rec = Region.new
150
+ logger.debug "create #{self.name}:" ## e.g. self.name => State, County, Muni, etc.
151
+ puts "[debug] StateBase.create_or_update_from_attribs calling #{self.name}.new" # note: assume self is derived class (object)
152
+ rec = self.new
139
153
  end
140
-
154
+
141
155
  logger.debug new_attributes.to_json
142
-
156
+
143
157
  rec.update_attributes!( new_attributes )
144
158
 
145
159
  #################
146
160
  # auto add capital cities
161
+ # - note: get added to top-level state (e.g. adm1)
147
162
 
148
163
  City.create_or_update_from_titles( value_cities,
149
- region_id: rec.id,
164
+ state_id: rec.state_id,
150
165
  country_id: rec.country_id )
151
166
 
152
- ### todo/fix: add captial ref to country/region
167
+ ### todo/fix: add captial ref to country/state
153
168
  ## todo/fix: use update_from_title and only allow one capital city
154
169
 
155
170
 
@@ -185,7 +200,8 @@ class Region < ActiveRecord::Base
185
200
 
186
201
 
187
202
 
188
- end # class Region
203
+ end # class State
189
204
 
190
205
  end # module Model
191
206
  end # module WorldDb
207
+
@@ -7,7 +7,7 @@ class Tag
7
7
 
8
8
  has_many :cities, :through => :taggings, :source => :taggable, source_type: 'WorldDb::Model::City', class_name: 'WorldDb::Model::City'
9
9
  has_many :countries, :through => :taggings, :source => :taggable, source_type: 'WorldDb::Model::Country', class_name: 'WorldDb::Model::Country'
10
- has_many :regions, :through => :taggings, :source => :taggable, source_type: 'WorldDb::Model::Region', class_name: 'WorldDb::Model::Region'
10
+ has_many :states, :through => :taggings, :source => :taggable, source_type: 'WorldDb::Model::State', class_name: 'WorldDb::Model::State'
11
11
 
12
12
  end # class Tag
13
13
 
@@ -42,30 +42,31 @@ require 'worlddb/models/forward'
42
42
  require 'worlddb/models/name'
43
43
  require 'worlddb/models/place'
44
44
  require 'worlddb/models/continent'
45
- require 'worlddb/models/continent_compat' # todo: move to compat gem
46
45
  require 'worlddb/models/country'
47
- require 'worlddb/models/country_compat' # todo: move to compat gem
48
46
  require 'worlddb/models/country_code'
49
- require 'worlddb/models/region'
50
- require 'worlddb/models/region_compat' # todo: move to compat gem
47
+ require 'worlddb/models/state_base'
48
+ require 'worlddb/models/state'
49
+ require 'worlddb/models/city_base'
51
50
  require 'worlddb/models/city'
52
- require 'worlddb/models/city_compat' # todo: move to compat gem
53
51
  require 'worlddb/models/lang'
54
- require 'worlddb/models/lang_compat' # todo: move to compat gem
55
52
  require 'worlddb/models/usage'
56
53
 
57
54
  require 'worlddb/models/tagdb/tag'
58
55
  require 'worlddb/models/tagdb/tagging'
59
56
 
57
+ require 'worlddb/helpers/value_helper' # Note: extends module TextUtils(!!)::ValueHelper
60
58
 
61
59
 
62
- require 'worlddb/schema' # NB: requires worlddb/models (include WorldDB::Models)
60
+ require 'worlddb/schema' # Note: requires worlddb/models (include WorldDB::Models)
63
61
  require 'worlddb/matcher'
62
+ require 'worlddb/matcher_adm'
64
63
 
64
+ require 'worlddb/readers/base'
65
65
  require 'worlddb/readers/lang'
66
66
  require 'worlddb/readers/usage'
67
67
  require 'worlddb/readers/country'
68
- require 'worlddb/readers/region'
68
+ require 'worlddb/readers/state'
69
+ require 'worlddb/readers/state_tree'
69
70
  require 'worlddb/readers/city'
70
71
 
71
72
  require 'worlddb/reader'
@@ -74,6 +75,8 @@ require 'worlddb/reader_zip'
74
75
  require 'worlddb/deleter'
75
76
  require 'worlddb/stats'
76
77
 
78
+ require 'worlddb/tree_reader'
79
+
77
80
 
78
81
  module WorldDb
79
82
 
@@ -33,11 +33,11 @@ module WorldDb
33
33
  COUNTRY_CODE_PATTERN_MESSAGE = "expected three uppercase letters A-Z (and _) /#{COUNTRY_CODE_PATTERN}/"
34
34
 
35
35
 
36
- REGION_KEY_PATTERN = '\A[a-z]+\z'
37
- REGION_KEY_PATTERN_MESSAGE = "expected one or more lowercase letters a-z /#{REGION_KEY_PATTERN}/"
36
+ STATE_KEY_PATTERN = '\A[a-z]+\z'
37
+ STATE_KEY_PATTERN_MESSAGE = "expected one or more lowercase letters a-z /#{STATE_KEY_PATTERN}/"
38
38
 
39
- REGION_CODE_PATTERN = '\A[A-Z_]{2,3}\z'
40
- REGION_CODE_PATTERN_MESSAGE = "expected two or three uppercase letters A-Z (and _) /#{REGION_CODE_PATTERN}/"
39
+ STATE_CODE_PATTERN = '\A[A-Z_]{2,3}\z'
40
+ STATE_CODE_PATTERN_MESSAGE = "expected two or three uppercase letters A-Z (and _) /#{STATE_CODE_PATTERN}/"
41
41
 
42
42
 
43
43
  CITY_KEY_PATTERN = '\A[a-z]{3,}\z'
@@ -10,7 +10,7 @@ class ReaderBase
10
10
  ## make models available in sportdb module by default with namespace
11
11
  # e.g. lets you use City instead of Models::City
12
12
  include Models
13
- include Matcher # e.g. match_cities_for_country, match_regions_for_country, etc.
13
+ include Matcher # e.g. match_cities_for_country, match_states_for_country, etc.
14
14
 
15
15
  ## value helpers e.g. is_year?, is_taglist? etc.
16
16
  include TextUtils::ValueHelper
@@ -21,9 +21,9 @@ class ReaderBase
21
21
 
22
22
 
23
23
  def initialize( opts={} )
24
- ## option: do NOT generate/add any tags for countries/regions/cities
24
+ ## option: do NOT generate/add any tags for countries/states/cities
25
25
  @skip_tags = opts[:skip_tags].present? ? true : false
26
- ## option: for now issue warning on update, that is, if key/record (country,region,city) already exists
26
+ ## option: for now issue warning on update, that is, if key/record (country,state,city) already exists
27
27
  @strict = opts[:strict].present? ? true : false
28
28
  end
29
29
 
@@ -80,56 +80,85 @@ class ReaderBase
80
80
  elsif match_cities_for_country( name ) do |country_key| # name =~ /\/([a-z]{2})\/cities/
81
81
  ## auto-add required country code (from folder structure)
82
82
  country = Country.find_by_key!( country_key )
83
- logger.debug "Country #{country.key} >#{country.title} (#{country.code})<"
83
+ logger.debug "Country #{country.key} >#{country.name} (#{country.code})<"
84
84
 
85
85
  r = create_city_reader( name, country_id: country.id )
86
86
  r.read()
87
87
  end
88
- elsif match_regions_abbr_for_country( name ) do |country_key| # name =~ /\/([a-z]{2})\/regions\.abbr/
89
- load_regions_xxx( country_key, 'abbr', name )
88
+ elsif match_tree_for_country( name ) do |country_key|
89
+ ## auto-add required country code (from folder structure)
90
+ country = Country.find_by_key!( country_key )
91
+ logger.debug "Country #{country.key} >#{country.name} (#{country.code})<"
92
+
93
+ r = create_tree_reader( name, country_id: country.id )
94
+ r.read()
90
95
  end
91
- elsif match_regions_iso_for_country( name ) do |country_key| # name =~ /\/([a-z]{2})\/regions\.iso/
92
- load_regions_xxx( country_key, 'iso', name )
96
+ elsif match_states_abbr_for_country( name ) do |country_key| # name =~ /\/([a-z]{2})\/states\.abbr/
97
+ load_states_xxx( country_key, 'abbr', name )
93
98
  end
94
- elsif match_regions_nuts_for_country( name ) do |country_key| # name =~ /\/([a-z]{2})\/regions\.nuts/
95
- load_regions_xxx( country_key, 'nuts', name )
99
+ elsif match_states_iso_for_country( name ) do |country_key| # name =~ /\/([a-z]{2})\/states\.iso/
100
+ load_states_xxx( country_key, 'iso', name )
96
101
  end
97
- elsif match_adm3_for_country( name ) do |country_key,region_key,adm2_name|
102
+ elsif match_states_nuts_for_country( name ) do |country_key| # name =~ /\/([a-z]{2})\/states\.nuts/
103
+ load_states_xxx( country_key, 'nuts', name )
104
+ end
105
+ elsif match_adm3_counties_for_country( name ) do |country_key, state_key, part_name|
98
106
  ## auto-add required country code (from folder structure)
99
107
  country = Country.find_by_key!( country_key )
100
- logger.debug "Country #{country.key} >#{country.title} (#{country.code})<"
101
- region = Region.find_by_key_and_country_id!( region_key, country.id )
102
- logger.debug "Region (Adm1) #{region.key} >#{region.title}<"
108
+ logger.debug "Country #{country.key} >#{country.name} (#{country.code})<"
109
+ state = State.find_by_key_and_country_id!( state_key, country.id )
110
+ logger.debug "State (ADM1) #{state.key} >#{state.name}<"
111
+
103
112
  ### todo: move find adm2 to model for (re)use !!!
104
- adm2 = Region.where( "lower(name) = ? AND country_id = ?",
105
- adm2_name, country.id ).first ## check - first needed? returns ary??
106
- if adm2.nil?
107
- puts "*** error/warn: fix - skipping adm3 - adm2 '#{adm2_name}' not found"
113
+ part = Part.where( "lower(name) = ? AND state_id = ?",
114
+ part_name, state.id ).first ## check - first needed? returns ary??
115
+ if part.nil?
116
+ logger.error "fix!! - skipping adm3_counties - part (ADM2) '#{part_name}' not found"
108
117
  next
109
118
  end
110
- logger.debug "Region (Adm2) #{adm2.key} >#{adm2.title}<"
119
+ logger.debug "Part (ADM2) #{part.key} >#{part.name}<"
111
120
 
112
- r = create_region_reader( name, country_id: country.id, region_id: adm2.id, level:3, c:true )
113
- r.read()
121
+ st = create_county_reader( name,
122
+ state_id: state.id,
123
+ part_id: part.id,
124
+ level: 3 ) # note: change county level to 3 (default is 2)
125
+ st.read()
114
126
  end
115
- elsif match_adm2_for_country( name ) do |country_key,region_key|
127
+ elsif match_adm2_counties_for_country( name ) do |country_key,state_key|
116
128
  ## auto-add required country code (from folder structure)
117
129
  country = Country.find_by_key!( country_key )
118
- logger.debug "Country #{country.key} >#{country.title} (#{country.code})<"
119
- region = Region.find_by_key_and_country_id!( region_key, country.id )
120
- logger.debug "Region (Adm1) #{region.key} >#{region.title}<"
121
-
122
- r = create_region_reader( name, country_id: country.id, region_id: region.id, level:2, d:true )
123
- r.read()
130
+ logger.debug "Country #{country.key} >#{country.name} (#{country.code})<"
131
+ state = State.find_by_key_and_country_id!( state_key, country.id )
132
+ logger.debug "State (ADM1) #{state.key} >#{state.name}<"
133
+
134
+ st = create_county_reader( name,
135
+ state_id: state.id,
136
+ ## part_id: nil,
137
+ level: 2 )
138
+ st.read()
139
+ end
140
+ elsif match_adm2_parts_for_country( name ) do |country_key,state_key|
141
+ ## auto-add required country code (from folder structure)
142
+ country = Country.find_by_key!( country_key )
143
+ logger.debug "Country #{country.key} >#{country.name} (#{country.code})<"
144
+ state = State.find_by_key_and_country_id!( state_key, country.id )
145
+ logger.debug "State (ADM2) #{state.key} >#{state.name}<"
146
+
147
+ st = create_part_reader( name,
148
+ state_id: state.id,
149
+ level: 2 )
150
+ st.read()
124
151
  end
125
- ### fix: change to match_adm1_for_country()
126
- elsif match_regions_for_country( name ) do |country_key| # name =~ /\/([a-z]{2})\/regions/
152
+ ### fix: change to match_adm1_states_for_country() - why? why not??
153
+ elsif match_states_for_country( name ) do |country_key| # name =~ /\/([a-z]{2})\/states/
127
154
  ## auto-add required country code (from folder structure)
128
155
  country = Country.find_by_key!( country_key )
129
- logger.debug "Country #{country.key} >#{country.title} (#{country.code})<"
156
+ logger.debug "Country #{country.key} >#{country.name} (#{country.code})<"
130
157
 
131
- r = create_region_reader( name, country_id: country.id, region_id: nil, level:1, s:true )
132
- r.read()
158
+ st = create_state_reader( name,
159
+ country_id: country.id,
160
+ level: 1 )
161
+ st.read()
133
162
  end
134
163
  else
135
164
  logger.error "unknown world.db fixture type >#{name}<"
@@ -138,17 +167,17 @@ class ReaderBase
138
167
  end
139
168
 
140
169
 
141
- ### use RegionAttrReader
142
- def load_regions_xxx( country_key, xxx, name )
170
+ ### use StateAttrReader
171
+ def load_states_xxx( country_key, xxx, name )
143
172
  country = Country.find_by_key!( country_key )
144
- logger.debug "Country #{country.key} >#{country.title} (#{country.code})<"
173
+ logger.debug "Country #{country.key} >#{country.name} (#{country.code})<"
145
174
 
146
175
  reader = create_hash_reader( name )
147
176
 
148
177
  reader.each do |key, value|
149
- region = Region.find_by_country_id_and_key!( country.id, key )
150
- region.send( "#{xxx}=", value )
151
- region.save!
178
+ state = State.find_by_country_id_and_key!( country.id, key )
179
+ state.send( "#{xxx}=", value )
180
+ state.save!
152
181
  end
153
182
  end
154
183
 
@@ -40,14 +40,47 @@ class Reader < ReaderBase
40
40
  CountryReader.from_file( path, more_attribs )
41
41
  end
42
42
 
43
- def create_region_reader( name, more_attribs={} )
43
+ def create_state_reader( name, more_attribs={} )
44
44
  path = "#{@include_path}/#{path_to_real_path(name)}.txt"
45
45
 
46
- logger.info "parsing data (region) '#{name}' (#{path})..."
46
+ logger.info "parsing data (state) '#{name}' (#{path})..."
47
47
 
48
- RegionReader.from_file( path, more_attribs )
48
+ StateReader.from_file( path, more_attribs )
49
49
  end
50
50
 
51
+ def create_part_reader( name, more_attribs={} )
52
+ path = "#{@include_path}/#{path_to_real_path(name)}.txt"
53
+
54
+ logger.info "parsing data (part) '#{name}' (#{path})..."
55
+
56
+ PartReader.from_file( path, more_attribs )
57
+ end
58
+
59
+ def create_county_reader( name, more_attribs={} )
60
+ path = "#{@include_path}/#{path_to_real_path(name)}.txt"
61
+
62
+ logger.info "parsing data (county) '#{name}' (#{path})..."
63
+
64
+ CountyReader.from_file( path, more_attribs )
65
+ end
66
+
67
+ def create_muni_reader( name, more_attribs={} )
68
+ path = "#{@include_path}/#{path_to_real_path(name)}.txt"
69
+
70
+ logger.info "parsing data (muni) '#{name}' (#{path})..."
71
+
72
+ MuniReader.from_file( path, more_attribs )
73
+ end
74
+
75
+
76
+ def create_tree_reader( name, more_attribs={} )
77
+ path = "#{@include_path}/#{path_to_real_path(name)}.txt"
78
+ logger.info "parsing data (state tree) '#{name}' (#{path})..."
79
+
80
+ StateTreeReader.from_file( path, more_attribs )
81
+ end
82
+
83
+
51
84
  def create_city_reader( name, more_attribs={} )
52
85
  path = "#{@include_path}/#{path_to_real_path(name)}.txt"
53
86
  logger.info "parsing data (city) '#{name}' (#{path})..."
@@ -85,13 +85,43 @@ class ZipReader < ReaderBase
85
85
  CountryReader.from_zip( @zip_file, path, more_attribs )
86
86
  end
87
87
 
88
- def create_region_reader( name, more_attribs={} )
88
+ def create_state_reader( name, more_attribs={} )
89
89
  path = name_to_zip_entry_path( name )
90
- logger.info "parsing data (region) in zip '#{name}' (#{path})..."
90
+ logger.info "parsing data (state) in zip '#{name}' (#{path})..."
91
91
 
92
- RegionReader.from_zip( @zip_file, path, more_attribs )
92
+ StateReader.from_zip( @zip_file, path, more_attribs )
93
93
  end
94
94
 
95
+ def create_part_reader( name, more_attribs={} )
96
+ path = name_to_zip_entry_path( name )
97
+ logger.info "parsing data (part) in zip '#{name}' (#{path})..."
98
+
99
+ PartReader.from_zip( @zip_file, path, more_attribs )
100
+ end
101
+
102
+ def create_county_reader( name, more_attribs={} )
103
+ path = name_to_zip_entry_path( name )
104
+ logger.info "parsing data (county) in zip '#{name}' (#{path})..."
105
+
106
+ CountyReader.from_zip( @zip_file, path, more_attribs )
107
+ end
108
+
109
+ def create_muni_reader( name, more_attribs={} )
110
+ path = name_to_zip_entry_path( name )
111
+ logger.info "parsing data (muni) in zip '#{name}' (#{path})..."
112
+
113
+ MuniReader.from_zip( @zip_file, path, more_attribs )
114
+ end
115
+
116
+
117
+ def create_tree_reader( name, more_attribs={} )
118
+ path = name_to_zip_entry_path( name )
119
+ logger.info "parsing data (state tree) in zip '#{name}' (#{path})..."
120
+
121
+ StateTreeReader.from_zip( @zip_file, path, more_attribs )
122
+ end
123
+
124
+
95
125
  def create_city_reader( name, more_attribs={} )
96
126
  path = name_to_zip_entry_path( name )
97
127
  logger.info "parsing data (city) in zip '#{name}' (#{path})..."