geonames_local 0.3.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,19 +1,23 @@
1
1
  = Geonames Local
2
2
 
3
- Download and store Geonames.org data.
3
+ Download and store (pg, mongo, tokyo) Geonames.org data.
4
4
  Making every Geoname API operation possible on your servers.
5
5
  No hit limit, fast as possible.
6
6
 
7
7
 
8
8
  == Usage
9
9
 
10
- To use the adapter, install the corresponding gem:
10
+ To use one adapter, install the corresponding gem:
11
11
 
12
12
  PostgreSQL => pg
13
- MongoDB => mongodb (optional: mongo_ext)
13
+ MongoDB => mongo (optional: mongo_ext)
14
14
  Tokyo => tokyocabinet
15
15
 
16
- Don't forget to install *unzip* and *curl*.
16
+ You will also need in your system:
17
+
18
+ * unzip
19
+ * curl
20
+
17
21
 
18
22
  === PostgreSQL
19
23
 
@@ -35,7 +39,7 @@ The file is self explanatory.
35
39
 
36
40
  geonames -c geonames.yml
37
41
 
38
- Work. Use -v for verbose.
42
+ To run it. Use -v for verbose.
39
43
 
40
44
  If you are not sure your country code, use:
41
45
 
@@ -45,7 +49,14 @@ If you are not sure your country code, use:
45
49
  == Relational Mapping
46
50
 
47
51
  When using PG, this gem will (try) to relational map Geonames
48
- data on your scheme. Postgresql done, tokyo still need heavy work.
52
+ data on your scheme.
53
+
54
+ == ActiveRecord
55
+
56
+ Check out lib/geonames/models/ar.rb
57
+
58
+ I`m wondering the best way (and if it`s a good idea) to auto include'em on rails.
59
+ For now, just copy as you see fit.
49
60
 
50
61
 
51
62
  == PostgreSQL
@@ -55,6 +66,7 @@ So, supposing ActiveRecord, something like this is possible:
55
66
  City.first.province.country.abbr
56
67
  => "BR"
57
68
 
69
+
58
70
  === Migration
59
71
 
60
72
  Default PG migration:
@@ -62,7 +74,7 @@ Default PG migration:
62
74
  create_table :cities do |t|
63
75
  t.references :country, :null => false
64
76
  t.references :province
65
- t.string :name, :null => false
77
+ t.string :name, :null => false
66
78
  t.point :geom, :srid => 4326
67
79
  t.integer :gid, :zip
68
80
  end
@@ -80,22 +92,25 @@ Default PG migration:
80
92
  end
81
93
 
82
94
  add_index :cities, :name
83
- add_index :cities, :gid
84
95
  add_index :cities, :zip
85
96
  add_index :cities, :country_id
86
97
  add_index :cities, :province_id
98
+ add_index :cities, :gid, :unique => true
87
99
  add_index :cities, :geom, :spatial => true
88
100
  add_index :provinces, :name
89
101
  add_index :provinces, :abbr
90
- add_index :provinces, :gid
91
102
  add_index :provinces, :country_id
103
+ add_index :provinces, :gid, :unique => true
104
+ add_index :countries, :abbr, :unique => true
105
+ add_index :countries, :name, :unique => true
92
106
 
93
107
 
94
- == Features/Problems
108
+ == TODO/Problems
95
109
 
96
110
  - Local relational mapping of geonames data
97
- - Map geonames fields to your db scheme UNDONE
111
+ - Map geonames fields to your db scheme
98
112
  - Countries are a static yml file :/
113
+ - IP Geonames? http://ipinfodb.com
99
114
 
100
115
 
101
116
  == Note on Patches/Pull Requests
data/Rakefile CHANGED
@@ -44,20 +44,13 @@ rescue LoadError
44
44
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
45
45
  end
46
46
 
47
- require 'spec/rake/spectask'
48
- Spec::Rake::SpecTask.new(:spec) do |spec|
49
- spec.libs << 'lib' << 'spec'
50
- spec.spec_files = FileList['spec/**/*_spec.rb']
47
+ require 'rspec/core/rake_task'
48
+ desc "Runs spec suite"
49
+ RSpec::Core::RakeTask.new(:spec) do |spec|
50
+ spec.pattern = 'spec/*_spec.rb'
51
+ spec.rspec_opts = ['--backtrace --colour']
51
52
  end
52
53
 
53
- Spec::Rake::SpecTask.new(:rcov) do |spec|
54
- spec.libs << 'lib' << 'spec'
55
- spec.pattern = 'spec/**/*_spec.rb'
56
- spec.rcov = true
57
- end
58
-
59
- task :spec => :check_dependencies
60
-
61
54
  task :default => :spec
62
55
 
63
56
  require 'rake/rdoctask'
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.1
1
+ 0.5.0
data/bin/geonames CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  $VERBOSE = true # -w
3
- $KCODE = "u" # -Ku
3
+ # $KCODE = "u" # -Ku
4
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
5
 
6
6
  require "geonames_cli"
data/geonames.yml CHANGED
@@ -1,14 +1,15 @@
1
1
  #
2
2
  # Geonames Local Config Example
3
3
  #
4
- :store: mongodb
4
+ :store: postgres
5
5
  :codes: [br]
6
6
  :level: city
7
+ :min_pop: 100000
7
8
  :mapping:
8
9
  :name: name
9
10
  :geom: true
10
11
  :db:
11
12
  :host: localhost
12
- :dbname: rtrac_development
13
+ :dbname: geonames_ar
13
14
  :user: postgres
14
15
  :password:
@@ -1,74 +1,71 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{geonames_local}
8
- s.version = "0.3.1"
8
+ s.version = "0.5.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Marcos Piccinini"]
12
- s.date = %q{2010-09-14}
12
+ s.date = %q{2011-04-24}
13
13
  s.default_executable = %q{geonames}
14
14
  s.description = %q{Dump and feed a tokyo cabinet for local geonames search}
15
15
  s.email = %q{x@nofxx.com}
16
16
  s.executables = ["geonames"]
17
17
  s.extra_rdoc_files = [
18
18
  "LICENSE",
19
- "README.rdoc"
19
+ "README.rdoc"
20
20
  ]
21
21
  s.files = [
22
22
  ".document",
23
- ".gitignore",
24
- "LICENSE",
25
- "README.rdoc",
26
- "Rakefile",
27
- "VERSION",
28
- "bin/geonames",
29
- "geonames.yml",
30
- "geonames_local.gemspec",
31
- "lib/geonames_ar.rb",
32
- "lib/geonames_cli.rb",
33
- "lib/geonames_local.rb",
34
- "lib/geonames_local/adapters/mongodb.rb",
35
- "lib/geonames_local/adapters/postgres.rb",
36
- "lib/geonames_local/adapters/tokyo.rb",
37
- "lib/geonames_local/cli.rb",
38
- "lib/geonames_local/config/codes.yml",
39
- "lib/geonames_local/config/geonames.sql",
40
- "lib/geonames_local/config/geonames.yml",
41
- "lib/geonames_local/data/dump.rb",
42
- "lib/geonames_local/data/export.rb",
43
- "lib/geonames_local/data/shp.rb",
44
- "lib/geonames_local/features/road.rb",
45
- "lib/geonames_local/features/spot.rb",
46
- "lib/geonames_local/features/zone.rb",
47
- "lib/geonames_local/geonames.rb",
48
- "lib/geonames_local/model/city.rb",
49
- "lib/geonames_local/model/country.rb",
50
- "lib/geonames_local/model/province.rb",
51
- "lib/geonames_local/mongo/city.rb",
52
- "lib/geonames_local/mongo/country.rb",
53
- "lib/geonames_local/mongo/province.rb",
54
- "spec/geonames_local/adapters/mongodb_spec.rb",
55
- "spec/geonames_local/adapters/postgres_spec.rb",
56
- "spec/geonames_local/adapters/tokyo_spec.rb",
57
- "spec/geonames_local/cli_spec.rb",
58
- "spec/geonames_local/data/cache_spec.rb",
59
- "spec/geonames_local/data/shp_spec.rb",
60
- "spec/geonames_local/features/road_spec.rb",
61
- "spec/geonames_local/features/spot_spec.rb",
62
- "spec/geonames_local/features/zone_spec.rb",
63
- "spec/geonames_local/model/ar_spec.rb",
64
- "spec/geonames_local/mongo/city_spec.rb",
65
- "spec/geonames_local_spec.rb",
66
- "spec/spec.opts",
67
- "spec/spec_ar_helper.rb",
68
- "spec/spec_helper.rb",
69
- "spec/spec_mongo_helper.rb",
70
- "task/benchmark.rb",
71
- "task/benchmark_cabinet.rb"
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/geonames",
28
+ "geonames.yml",
29
+ "geonames_local.gemspec",
30
+ "lib/geonames_ar.rb",
31
+ "lib/geonames_cli.rb",
32
+ "lib/geonames_local.rb",
33
+ "lib/geonames_local/adapters/mongodb.rb",
34
+ "lib/geonames_local/adapters/postgres.rb",
35
+ "lib/geonames_local/adapters/tokyo.rb",
36
+ "lib/geonames_local/cli.rb",
37
+ "lib/geonames_local/config/codes.yml",
38
+ "lib/geonames_local/config/geonames.sql",
39
+ "lib/geonames_local/config/geonames.yml",
40
+ "lib/geonames_local/data/dump.rb",
41
+ "lib/geonames_local/data/export.rb",
42
+ "lib/geonames_local/data/shp.rb",
43
+ "lib/geonames_local/data/sync.rb",
44
+ "lib/geonames_local/features/road.rb",
45
+ "lib/geonames_local/features/spot.rb",
46
+ "lib/geonames_local/features/zone.rb",
47
+ "lib/geonames_local/geonames.rb",
48
+ "lib/geonames_local/models/ar.rb",
49
+ "lib/geonames_local/models/mongo.rb",
50
+ "lib/geonames_local/models/tokyo.rb",
51
+ "spec/geonames_local/adapters/mongodb_spec.rb",
52
+ "spec/geonames_local/adapters/postgres_spec.rb",
53
+ "spec/geonames_local/adapters/tokyo_spec.rb",
54
+ "spec/geonames_local/cli_spec.rb",
55
+ "spec/geonames_local/data/cache_spec.rb",
56
+ "spec/geonames_local/data/dump_spec.rb",
57
+ "spec/geonames_local/data/shp_spec.rb",
58
+ "spec/geonames_local/features/road_spec.rb",
59
+ "spec/geonames_local/features/spot_spec.rb",
60
+ "spec/geonames_local/features/zone_spec.rb",
61
+ "spec/geonames_local/models/ar_spec.rb",
62
+ "spec/geonames_local/models/mongo_spec.rb",
63
+ "spec/geonames_local_spec.rb",
64
+ "spec/spec_ar_helper.rb",
65
+ "spec/spec_helper.rb",
66
+ "spec/spec_mongo_helper.rb",
67
+ "task/benchmark.rb",
68
+ "task/benchmark_cabinet.rb"
72
69
  ]
73
70
  s.homepage = %q{http://github.com/nofxx/geonames_local}
74
71
  s.post_install_message = %q{
@@ -94,26 +91,26 @@ http://github.com/mongodb/mongo-ruby-driver
94
91
 
95
92
  Have fun because:
96
93
  }
97
- s.rdoc_options = ["--charset=UTF-8"]
98
94
  s.require_paths = ["lib"]
99
95
  s.rubygems_version = %q{1.3.7}
100
96
  s.summary = %q{Dump and feed a tokyo local geonames db}
101
97
  s.test_files = [
98
+ "spec/geonames_local/adapters/mongodb_spec.rb",
99
+ "spec/geonames_local/adapters/postgres_spec.rb",
100
+ "spec/geonames_local/adapters/tokyo_spec.rb",
101
+ "spec/geonames_local/cli_spec.rb",
102
+ "spec/geonames_local/data/cache_spec.rb",
103
+ "spec/geonames_local/data/dump_spec.rb",
104
+ "spec/geonames_local/data/shp_spec.rb",
105
+ "spec/geonames_local/features/road_spec.rb",
106
+ "spec/geonames_local/features/spot_spec.rb",
107
+ "spec/geonames_local/features/zone_spec.rb",
108
+ "spec/geonames_local/models/ar_spec.rb",
109
+ "spec/geonames_local/models/mongo_spec.rb",
110
+ "spec/geonames_local_spec.rb",
102
111
  "spec/spec_ar_helper.rb",
103
- "spec/spec_helper.rb",
104
- "spec/geonames_local/data/shp_spec.rb",
105
- "spec/geonames_local/data/cache_spec.rb",
106
- "spec/geonames_local/model/ar_spec.rb",
107
- "spec/geonames_local/mongo/city_spec.rb",
108
- "spec/geonames_local/cli_spec.rb",
109
- "spec/geonames_local/adapters/postgres_spec.rb",
110
- "spec/geonames_local/adapters/tokyo_spec.rb",
111
- "spec/geonames_local/adapters/mongodb_spec.rb",
112
- "spec/geonames_local/features/spot_spec.rb",
113
- "spec/geonames_local/features/zone_spec.rb",
114
- "spec/geonames_local/features/road_spec.rb",
115
- "spec/spec_mongo_helper.rb",
116
- "spec/geonames_local_spec.rb"
112
+ "spec/spec_helper.rb",
113
+ "spec/spec_mongo_helper.rb"
117
114
  ]
118
115
 
119
116
  if s.respond_to? :specification_version then
data/lib/geonames_ar.rb CHANGED
@@ -4,11 +4,9 @@
4
4
  $:.unshift(File.dirname(__FILE__)) unless
5
5
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
6
6
 
7
+ # Adapter = Geonames::Postgres.new(Opt[:db])
7
8
  # Require Libs
8
9
  require 'geonames_local/geonames'
9
10
 
10
- require 'geonames_local/model/country'
11
- require 'geonames_local/model/province'
12
- require 'geonames_local/model/city'
11
+ require 'geonames_local/models/ar'
13
12
  #require 'geonames_local/data/shp'
14
-
data/lib/geonames_cli.rb CHANGED
@@ -6,8 +6,9 @@ $:.unshift(File.dirname(__FILE__)) unless
6
6
 
7
7
  # Require CLI Stuff
8
8
  require 'geonames_local/geonames'
9
- require 'geonames_local/cli'
10
9
  require 'geonames_local/data/shp'
11
10
  require 'geonames_local/data/dump'
11
+ require 'geonames_local/data/sync'
12
12
  require 'geonames_local/data/export'
13
+ require 'geonames_local/cli'
13
14
 
@@ -78,7 +78,8 @@ module Geonames
78
78
  # getNear command returns distance too
79
79
  # <1.9 needs OrderedHash
80
80
  def near(resource, x, y, limit=nil)
81
- cmd = OrderedHash.new
81
+ # FIXME: Better explicity require OrderedHash?
82
+ cmd = Object.const_defined?("OrderedHash") ? OrderedHash.new : { }
82
83
  cmd["geoNear"] = resource
83
84
  cmd["near"] = sin_proj(x,y)
84
85
  cmd["num"] = limit if limit
@@ -5,27 +5,30 @@ module Geonames
5
5
  Countries = {}
6
6
  Provinces = {}
7
7
 
8
- def initialize(opts) #table, addr = "localhost", port = 5432)
8
+ def initialize(opts={}) #table, addr = "localhost", port = 5432)
9
9
  @conn = PGconn.new(opts)
10
10
  end
11
11
 
12
12
  #
13
13
  # Get Country and Province ID from the DB
14
+ #
15
+ # Maps the FKs ids correctly for our bank
16
+ #
14
17
  def get_some_ids(some)
15
- c = Countries[some.country] ||=
18
+ cid = Countries[some.country] ||=
16
19
  @conn.exec("SELECT countries.id FROM countries WHERE UPPER(countries.abbr) = UPPER('#{some.country}')")[0]["id"] rescue nil
17
- c ||= write("countries", {:name => Codes[some.country.downcase.to_sym][:pt_br], :abbr => some.country })
20
+ cid ||= write("countries", {:name => Codes[some.country.downcase.to_sym][:pt_br], :abbr => some.country })
18
21
 
19
- p = nil
20
- ci = nil
22
+ pid = nil
23
+ tid = nil
21
24
  if some.kind_of? Spot
22
- p = Provinces[some.province] ||= find("provinces", Cache[:provinces].
25
+ pid = Provinces[some.province] ||= find("provinces", Cache[:provinces].
23
26
  find{ |p| p.province == some.province}.gid)
24
27
  else
25
- ci = find("cities", some.city)
26
- p = @conn.exec("SELECT cities.province_id FROM cities WHERE cities.id = #{ci}")[0]["province_id"] rescue nil
28
+ tid = find("cities", some.city)
29
+ pid = @conn.exec("SELECT cities.province_id FROM cities WHERE cities.id = #{tid}")[0]["province_id"] rescue nil
27
30
  end
28
- [c, p, ci]
31
+ [cid, pid, tid]
29
32
  end
30
33
 
31
34
  #
@@ -33,22 +36,25 @@ module Geonames
33
36
  def insert(table, some)
34
37
  country_id, province_id, city_id = get_some_ids(some)
35
38
  case table
36
- when :cities
39
+ when :city
37
40
  write("cities", {:name => some.name, :country_id => country_id,
38
41
  :geom => some.geom.as_hex_ewkb, :gid => some.gid,
39
42
  :zip => some.zip, :province_id => province_id})
40
- when :provinces
43
+ when :province
41
44
  write("provinces", { :name => some.name, :abbr => some.abbr,
42
45
  :country_id => country_id, :gid => some.gid })
43
- when :roads
46
+ when :road
44
47
  write("roads", { :name => some.name, :geom => some.geom.as_hex_ewkb, :kind => some.kind,
45
48
  :country_id => country_id, :city_id => city_id, :province_id => province_id })
49
+ else
50
+ puts "Fail to insert #{some}"
46
51
  end
47
52
  end
48
53
 
49
54
  #
50
55
  # Find a record`s ID
51
- def find(table, id, name=nil)
56
+ def find(kind, id, name=nil)
57
+ table = get_table kind
52
58
  begin
53
59
  if name
54
60
  @conn.exec("SELECT #{table}.id FROM #{table} WHERE (#{table}.name = E'#{id}')")[0]["id"]
@@ -79,6 +85,15 @@ module Geonames
79
85
  end.join(",")
80
86
  end
81
87
 
88
+ def get_table(kind)
89
+ case kind
90
+ when :city then "cities"
91
+ when :country then "countries"
92
+ else
93
+ kind.to_s + "s"
94
+ end
95
+ end
96
+
82
97
  #
83
98
  # Naive PG insert ORM =D
84
99
  def write(table, hsh)
@@ -60,6 +60,11 @@ BANNER
60
60
  Opt.merge! YAML.load(File.read(Opt[:config]))
61
61
  end
62
62
 
63
+ # Load config/geonames.yml if there's one
64
+ if File.exists?(cfg = File.join("config", "geonames.yml"))
65
+ Opt.merge! YAML.load(File.read(cfg))
66
+ end
67
+
63
68
  if shp = Opt[:shp]
64
69
  SHP.import(shp)
65
70
  exit
@@ -94,69 +99,14 @@ BANNER
94
99
  if argv[0] =~ /csv|json/
95
100
  Geonames::Export.new(Country.all).to_csv
96
101
  else
97
- db = load_adapter(Opt[:store])
98
102
  info "Using adapter #{Opt[:store]}.."
99
103
  Geonames::Dump.work(Opt[:codes], :zip) #rescue puts "Command not found: #{comm} #{@usage}"
100
104
  Geonames::Dump.work(Opt[:codes], :dump) #rescue puts "Command not found: #{comm} #{@usage}"
101
105
  info "\n---\nTotal #{Cache[:dump].length} parsed. #{Cache[:zip].length} zips."
102
- info "Join dump << zip"
103
- unify!
104
- write_to_store!(db)
105
- end
106
- end
107
-
108
- def load_adapter(name)
109
- begin
110
- require "geonames_local/adapters/#{name}"
111
- Geonames.class_eval(name.capitalize).new(Opt[:db])
112
- rescue LoadError
113
- puts "Can't find adapter #{name}"
114
- stop!
106
+ Sync.work!
115
107
  end
116
108
  end
117
109
 
118
- def write_to_store!(db)
119
- groups = Cache[:dump].group_by(&:kind)
120
- Cache[:provinces] = groups[:provinces]
121
- # ensure this order....
122
- do_write(db, groups[:provinces])
123
- do_write(db, groups[:cities])
124
- end
125
-
126
- def do_write(db, values)
127
- return if values.empty?
128
- key = values[0].table
129
- start = Time.now
130
- writt = 0
131
- info "\nWriting #{values.length} #{key}..."
132
- values.each do |val|
133
- meth = val.respond_to?(:gid) ? [val.gid] : [val.name, true]
134
- unless db.find(val.table, *meth)
135
- db.insert(val.table, val)
136
- writt += 1
137
- end
138
- end
139
- total = Time.now - start
140
- info "#{writt} #{key} written in #{total} sec (#{(writt/total).to_i}/s)"
141
- end
142
-
143
- def unify!
144
- start = Time.now
145
- Cache[:dump].map! do |spot|
146
- if other = Cache[:zip].find { |d| d.code == spot.code }
147
- spot.zip = other.zip
148
- spot
149
- else
150
- spot
151
- end
152
- end
153
- info "Done. #{(Time.now-start).to_i}s"
154
- end
155
-
156
- def stop!
157
- puts "Closing Geonames..."
158
- exit
159
- end
160
110
  end
161
111
 
162
112
  end