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.
- 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})..."
|