worlddb-models 2.2.2 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Manifest.txt +31 -13
- data/README.md +7 -7
- data/Rakefile +1 -1
- data/lib/worlddb/deleter.rb +6 -1
- data/lib/worlddb/helpers/value_helper.rb +117 -0
- data/lib/worlddb/matcher.rb +99 -135
- data/lib/worlddb/matcher_adm.rb +82 -0
- data/lib/worlddb/models/city.rb +30 -208
- data/lib/worlddb/models/city_base.rb +220 -0
- data/lib/worlddb/models/continent.rb +9 -0
- data/lib/worlddb/models/country.rb +21 -4
- data/lib/worlddb/models/forward.rb +25 -9
- data/lib/worlddb/models/lang.rb +6 -0
- data/lib/worlddb/models/place.rb +1 -1
- data/lib/worlddb/models/state.rb +83 -0
- data/lib/worlddb/models/{region.rb → state_base.rb} +52 -36
- data/lib/worlddb/models/tagdb/tag.rb +1 -1
- data/lib/worlddb/models.rb +11 -8
- data/lib/worlddb/patterns.rb +4 -4
- data/lib/worlddb/reader.rb +68 -39
- data/lib/worlddb/reader_file.rb +36 -3
- data/lib/worlddb/reader_zip.rb +33 -3
- data/lib/worlddb/readers/base.rb +149 -0
- data/lib/worlddb/readers/city.rb +2 -65
- data/lib/worlddb/readers/country.rb +2 -63
- data/lib/worlddb/readers/lang.rb +3 -68
- data/lib/worlddb/readers/state.rb +61 -0
- data/lib/worlddb/readers/state_tree.rb +118 -0
- data/lib/worlddb/readers/usage.rb +2 -65
- data/lib/worlddb/schema.rb +142 -43
- data/lib/worlddb/stats.rb +7 -4
- data/lib/worlddb/tree_reader.rb +97 -0
- data/lib/worlddb/version.rb +2 -2
- data/test/adm/test_fixture_matcher_adm2.rb +73 -0
- data/test/{test_fixture_matcher_adm3.rb → adm/test_fixture_matcher_adm3.rb} +6 -6
- data/test/adm/test_fixture_matcher_tree.rb +52 -0
- data/test/{test_read_adm.rb → adm/test_read_adm.rb} +13 -20
- data/test/adm/test_read_tree.rb +63 -0
- data/test/data/at-austria/2--n-niederoesterreich/counties.txt +6 -4
- data/test/data/at-austria/orte.txt +23 -0
- data/test/data/at-austria/setups/tree.txt +9 -0
- data/test/data/de-deutschland/3--by-bayern/4--oberfranken/counties.txt +14 -13
- data/test/data/de-deutschland/3--by-bayern/4--oberfranken/orte.txt +104 -0
- data/test/data/de-deutschland/3--by-bayern/4--oberfranken/orte_ii.txt +17 -0
- data/test/data/de-deutschland/3--by-bayern/{districts.txt → parts.txt} +1 -1
- data/test/data/de-deutschland/orte.txt +12 -0
- data/test/data/de-deutschland/setups/adm.txt +1 -1
- data/test/data/de-deutschland/setups/tree.txt +9 -0
- data/test/helper.rb +8 -1
- data/test/test_fixture_matchers.rb +9 -10
- data/test/test_fixture_matchers_ii.rb +20 -19
- data/test/test_model_city.rb +26 -9
- data/test/{test_model_comp.rb → test_model_compat.rb} +15 -13
- data/test/test_model_country.rb +1 -1
- data/test/test_model_state.rb +54 -0
- data/test/test_model_states_at.rb +111 -0
- data/test/test_model_states_de.rb +147 -0
- data/test/test_models.rb +10 -3
- data/test/test_parse_city.rb +70 -0
- data/test/test_parse_country.rb +56 -0
- data/test/test_parse_state.rb +46 -0
- data/test/test_state_tree_reader_at.rb +54 -0
- data/test/test_state_tree_reader_de.rb +71 -0
- data/test/test_tree_reader.rb +39 -0
- metadata +50 -22
- data/lib/worlddb/models/city_compat.rb +0 -27
- data/lib/worlddb/models/continent_compat.rb +0 -24
- data/lib/worlddb/models/country_compat.rb +0 -35
- data/lib/worlddb/models/lang_compat.rb +0 -23
- data/lib/worlddb/models/region_compat.rb +0 -26
- data/lib/worlddb/readers/region.rb +0 -79
- data/test/test_fixture_matcher_adm2.rb +0 -62
- 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
|
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?,
|
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: /#{
|
23
|
-
validates :code, format: { with: /#{
|
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: '
|
27
|
-
belongs_to :parent, class_name: '
|
28
|
-
has_many :
|
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
|
-
|
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 =~ /#{
|
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
|
-
|
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
|
148
|
+
logger.debug "update #{self.name} #{rec.id}-#{rec.key}:"
|
136
149
|
else
|
137
|
-
logger.debug "create
|
138
|
-
|
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
|
-
|
164
|
+
state_id: rec.state_id,
|
150
165
|
country_id: rec.country_id )
|
151
166
|
|
152
|
-
### todo/fix: add captial ref to country/
|
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
|
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 :
|
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
|
|
data/lib/worlddb/models.rb
CHANGED
@@ -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/
|
50
|
-
require 'worlddb/models/
|
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' #
|
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/
|
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
|
|
data/lib/worlddb/patterns.rb
CHANGED
@@ -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
|
-
|
37
|
-
|
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
|
-
|
40
|
-
|
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'
|
data/lib/worlddb/reader.rb
CHANGED
@@ -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,
|
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/
|
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,
|
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.
|
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
|
89
|
-
|
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
|
92
|
-
|
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
|
95
|
-
|
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
|
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.
|
101
|
-
|
102
|
-
logger.debug "
|
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
|
-
|
105
|
-
|
106
|
-
if
|
107
|
-
|
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 "
|
119
|
+
logger.debug "Part (ADM2) #{part.key} >#{part.name}<"
|
111
120
|
|
112
|
-
|
113
|
-
|
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
|
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.
|
119
|
-
|
120
|
-
logger.debug "
|
121
|
-
|
122
|
-
|
123
|
-
|
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
|
126
|
-
elsif
|
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.
|
156
|
+
logger.debug "Country #{country.key} >#{country.name} (#{country.code})<"
|
130
157
|
|
131
|
-
|
132
|
-
|
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
|
142
|
-
def
|
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.
|
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
|
-
|
150
|
-
|
151
|
-
|
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
|
|
data/lib/worlddb/reader_file.rb
CHANGED
@@ -40,14 +40,47 @@ class Reader < ReaderBase
|
|
40
40
|
CountryReader.from_file( path, more_attribs )
|
41
41
|
end
|
42
42
|
|
43
|
-
def
|
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 (
|
46
|
+
logger.info "parsing data (state) '#{name}' (#{path})..."
|
47
47
|
|
48
|
-
|
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})..."
|
data/lib/worlddb/reader_zip.rb
CHANGED
@@ -85,13 +85,43 @@ class ZipReader < ReaderBase
|
|
85
85
|
CountryReader.from_zip( @zip_file, path, more_attribs )
|
86
86
|
end
|
87
87
|
|
88
|
-
def
|
88
|
+
def create_state_reader( name, more_attribs={} )
|
89
89
|
path = name_to_zip_entry_path( name )
|
90
|
-
logger.info "parsing data (
|
90
|
+
logger.info "parsing data (state) in zip '#{name}' (#{path})..."
|
91
91
|
|
92
|
-
|
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})..."
|