geonames_dump 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +4 -0
- data/LICENSE +23 -0
- data/README.md +85 -0
- data/Rakefile +2 -0
- data/geonames_dump.gemspec +20 -0
- data/lib/generators/geonames_dump/install_generator.rb +32 -0
- data/lib/generators/geonames_dump/templates/app/models/geonames_admin1.rb +2 -0
- data/lib/generators/geonames_dump/templates/app/models/geonames_admin2.rb +2 -0
- data/lib/generators/geonames_dump/templates/app/models/geonames_city.rb +2 -0
- data/lib/generators/geonames_dump/templates/app/models/geonames_country.rb +25 -0
- data/lib/generators/geonames_dump/templates/app/models/geonames_feature.rb +49 -0
- data/lib/generators/geonames_dump/templates/db/migrate/create_geonames_countries.rb +38 -0
- data/lib/generators/geonames_dump/templates/db/migrate/create_geonames_features.rb +64 -0
- data/lib/generators/geonames_dump/templates/piktur_config.rb +19 -0
- data/lib/geonames_dump/blocks.rb +31 -0
- data/lib/geonames_dump/railtie.rb +11 -0
- data/lib/geonames_dump/version.rb +3 -0
- data/lib/geonames_dump.rb +8 -0
- data/lib/tasks/import.rake +257 -0
- data/lib/tasks/install.rake +4 -0
- data/lib/tasks/migrate.rake +34 -0
- data/lib/tasks/truncate.rake +40 -0
- metadata +110 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0d54cf96d1f31ae2a2fd2a94b6d8badeb317e0df
|
4
|
+
data.tar.gz: b2a120c181cc803aae3172523013206e2efa3f46
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2bb9c4fddd4bc7838967891358be49dd1ef1a999275223e524a939515a58d85882a90f05fbea423a1b1abb7db9f9aa2ad79292c6e39ac217962cefde3f0bd4b2
|
7
|
+
data.tar.gz: de04975b021b84aea162b710124fefa8fbe06b55ca4c4c6b8429426088efa9a016651307656245633cacb26a571b28b31c4590c4691727dff96199ea60722d36
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2012 Thomas Kienlen, La Fourmi Immo
|
2
|
+
Including original code Copyright (c) 2009 Alex Pooley, Brown Beagle Software
|
3
|
+
|
4
|
+
MIT License
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# GeonamesDump
|
2
|
+
|
3
|
+
GeonamesDump import geographic data from geonames project into your application, avoiding to use external service like google maps.
|
4
|
+
It's a "gem" version of the application [brownbeagle/geonames](https://github.com/brownbeagle/geonames).
|
5
|
+
Now you only need to include the dependency into your Gemfile and your project will include geonames.
|
6
|
+
|
7
|
+
You're free to use [geocoder](https://github.com/alexreisner/geocoder) or [geokit](https://github.com/imajes/geokit) or any other geocoding solution.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'geonames_dump'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle install
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install geonames_dump
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
Create models and migration files
|
26
|
+
|
27
|
+
$ rails generate geonames_dump:install
|
28
|
+
|
29
|
+
Import data (takes a loonnnng time!), it will download data, import countries and many features (Countries, Cities, Admin1 (first administrative subdivision), Admin2 (second level administrative subdivision))
|
30
|
+
|
31
|
+
$ rake geonames_dump:install
|
32
|
+
|
33
|
+
If you need more fine grained control over the installation process you can run individual geoname rake tasks instead of the all-in-one install :
|
34
|
+
|
35
|
+
$ rake -T | grep geonames_dump
|
36
|
+
|
37
|
+
rake geonames_dump:import:all # Import ALL geonames data.
|
38
|
+
rake geonames_dump:import:many # Import most of geonames data.
|
39
|
+
|
40
|
+
rake geonames_dump:import:admin1 # Import admin1 codes
|
41
|
+
rake geonames_dump:import:admin2 # Import admin2 codes
|
42
|
+
rake geonames_dump:import:cities # Import all cities, regardless of population.
|
43
|
+
rake geonames_dump:import:cities1000 # Import cities with population greater than 1000
|
44
|
+
rake geonames_dump:import:cities15000 # Import cities with population greater than 15000
|
45
|
+
rake geonames_dump:import:cities5000 # Import cities with population greater than 5000
|
46
|
+
rake geonames_dump:import:countries # Import countries informations
|
47
|
+
rake geonames_dump:import:features # Import feature data.
|
48
|
+
|
49
|
+
rake geonames_dump:truncate:all # Truncate all geonames data.
|
50
|
+
rake geonames_dump:truncate:countries # Truncate countries informations
|
51
|
+
rake geonames_dump:truncate:admin1 # Truncate admin1 codes
|
52
|
+
rake geonames_dump:truncate:admin2 # Truncate admin2 codes
|
53
|
+
rake geonames_dump:truncate:cities # Truncate cities informations
|
54
|
+
rake geonames_dump:truncate:features # Truncate features informations
|
55
|
+
|
56
|
+
## Geonames data usage
|
57
|
+
|
58
|
+
The above commands will import geonames data in your Rails application, in other words, this will create models and fill database with place/city/country informations.
|
59
|
+
Now to find a city for example :
|
60
|
+
|
61
|
+
GeonamesFeature.search('paris')
|
62
|
+
|
63
|
+
If your request is ambiguous, like not searching Dublin in Ireland but Dublin in the USA, you may specify country :
|
64
|
+
|
65
|
+
GeonamesFeature.search('dublin, us')
|
66
|
+
|
67
|
+
Models available allows to specify the type of place you want to search for :
|
68
|
+
|
69
|
+
- GeonamesAdmin1, for first level of adminstrative subdivision
|
70
|
+
- GeonamesAdmin2, for second level of adminstrative subdivision
|
71
|
+
- GeonamesCity, for city names
|
72
|
+
- GeonamesFeature, for generic names including all the above
|
73
|
+
- GeonamesCountry, for country names
|
74
|
+
|
75
|
+
Searching for a city like dublin may be done using :
|
76
|
+
|
77
|
+
GeonamesCity.search('dublin')
|
78
|
+
|
79
|
+
## Contributing
|
80
|
+
|
81
|
+
1. Fork it
|
82
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
83
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
84
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
85
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/geonames_dump/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Alex Pooley", "Thomas Kienlen"]
|
6
|
+
gem.email = ["thomas.kienlen@lafourmi-immo.com"]
|
7
|
+
gem.description = %q{GeonamesDump import geographic data from geonames project into your application, avoiding to use external service like Google Maps.}
|
8
|
+
gem.summary = %q{Import data from Geonames}
|
9
|
+
gem.homepage = "https://github.com/kmmndr/geonames_dump"
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "geonames_dump"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = GeonamesDump::VERSION
|
17
|
+
gem.add_runtime_dependency 'ruby-progressbar'
|
18
|
+
gem.add_runtime_dependency 'activerecord-reset-pk-sequence'
|
19
|
+
gem.add_runtime_dependency 'rubyzip'
|
20
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module GeonamesDump
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
include Rails::Generators::Migration
|
5
|
+
source_root File.expand_path(File.join(File.dirname(__FILE__), 'templates'))
|
6
|
+
|
7
|
+
desc <<DESC
|
8
|
+
Description:
|
9
|
+
Create Geonames initial migrations files and Geonames model files in your application
|
10
|
+
DESC
|
11
|
+
def copy_migrations_files
|
12
|
+
#template File.join('app', 'models', 'geonames_country.rb', 'config/initializers/piktur_config.rb'
|
13
|
+
%w(create_geonames_countries create_geonames_features).each do |file|
|
14
|
+
migration_template File.join('db', 'migrate', "#{file}.rb")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def copy_models_files
|
19
|
+
#template File.join('app', 'models', 'geonames_country.rb', 'config/initializers/piktur_config.rb'
|
20
|
+
%w(geonames_admin1 geonames_admin2 geonames_city geonames_country geonames_feature).each do |file|
|
21
|
+
copy_file File.join('app', 'models', "#{file}.rb")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.next_migration_number(path)
|
26
|
+
sleep 1 # OPTIMIZE: there might be a better way to do this ...
|
27
|
+
@migration_number = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i.to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class GeonamesCountry < ActiveRecord::Base
|
2
|
+
validates_uniqueness_of :geonameid
|
3
|
+
|
4
|
+
##
|
5
|
+
# search by iso first, then by name if not found
|
6
|
+
#
|
7
|
+
scope :search, lambda { |q|
|
8
|
+
by_iso(q).count > 0 ? by_iso(q) : by_name(q)
|
9
|
+
}
|
10
|
+
|
11
|
+
##
|
12
|
+
# search by iso code
|
13
|
+
#
|
14
|
+
scope :by_iso, lambda { |q|
|
15
|
+
where("iso = ? or iso3 = ?", q.upcase, q.upcase)
|
16
|
+
}
|
17
|
+
|
18
|
+
##
|
19
|
+
# search by name
|
20
|
+
#
|
21
|
+
scope :by_name, lambda { |q|
|
22
|
+
where("country LIKE ?", "#{q}%")
|
23
|
+
}
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class GeonamesFeature < ActiveRecord::Base
|
2
|
+
validates_uniqueness_of :geonameid
|
3
|
+
before_save :set_asciiname_first_letters
|
4
|
+
|
5
|
+
##
|
6
|
+
# Search for feature, searches might include country (separated by ',')
|
7
|
+
#
|
8
|
+
scope :search, lambda { |query|
|
9
|
+
virgule = query.include? ','
|
10
|
+
|
11
|
+
splited = virgule ? query.split(',') : [query]
|
12
|
+
|
13
|
+
country = virgule ? splited.last.strip : nil
|
14
|
+
|
15
|
+
queries = virgule ? splited[0...-1] : splited
|
16
|
+
queries = queries.join(' ').split(' ')
|
17
|
+
|
18
|
+
ret = by_name(*queries)
|
19
|
+
|
20
|
+
unless country.nil?
|
21
|
+
geonames_country = GeonamesCountry.search(country).first
|
22
|
+
ret = ret.where(:country => geonames_country.iso) unless geonames_country.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
ret
|
26
|
+
}
|
27
|
+
|
28
|
+
##
|
29
|
+
# Find by names
|
30
|
+
#
|
31
|
+
scope :by_name, lambda { |*queries|
|
32
|
+
ret = self.scoped
|
33
|
+
count = queries.count
|
34
|
+
queries.collect.with_index do |q, idx|
|
35
|
+
query = idx == 0 ? "#{q}" : "%#{q}%"
|
36
|
+
ret = ret.where("asciiname_first_letters = ?", q[0...3].downcase)
|
37
|
+
ret = ret.where("name LIKE ? or asciiname LIKE ?", query, query)
|
38
|
+
end
|
39
|
+
ret
|
40
|
+
}
|
41
|
+
|
42
|
+
##
|
43
|
+
# Set first letters of name into index column
|
44
|
+
#
|
45
|
+
def set_asciiname_first_letters
|
46
|
+
self.asciiname_first_letters = self.asciiname[0...3].downcase unless self.asciiname.nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
# http://download.geonames.org/export/dump/countryInfo.txt
|
3
|
+
|
4
|
+
class CreateGeonamesCountries < ActiveRecord::Migration
|
5
|
+
|
6
|
+
def self.up
|
7
|
+
create_table :geonames_countries do |t|
|
8
|
+
t.string :iso
|
9
|
+
t.string :iso3
|
10
|
+
t.string :iso_numeric
|
11
|
+
t.string :fips
|
12
|
+
t.string :country
|
13
|
+
t.string :capital
|
14
|
+
t.integer :area # in sq. km
|
15
|
+
t.integer :population
|
16
|
+
t.string :continent
|
17
|
+
t.string :tld
|
18
|
+
t.string :currency_code
|
19
|
+
t.string :currency_name
|
20
|
+
t.string :phone
|
21
|
+
t.string :postal_code_format
|
22
|
+
t.string :postal_code_regex
|
23
|
+
t.string :languages
|
24
|
+
t.integer :geonameid
|
25
|
+
t.string :neighbours
|
26
|
+
t.string :equivalent_fips_code
|
27
|
+
|
28
|
+
t.timestamps
|
29
|
+
end
|
30
|
+
|
31
|
+
add_index :geonames_countries, :geonameid
|
32
|
+
add_index :geonames_countries, :country
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.down
|
36
|
+
drop_table :geonames_countries
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class CreateGeonamesFeatures < ActiveRecord::Migration
|
2
|
+
|
3
|
+
# geonameid : integer id of record in geonames database
|
4
|
+
# name : name of geographical point (utf8) varchar(200)
|
5
|
+
# asciiname : name of geographical point in plain ascii characters, varchar(200)
|
6
|
+
# alternatenames : alternatenames, comma separated varchar(4000) (varchar(5000) for SQL Server)
|
7
|
+
# latitude : latitude in decimal degrees (wgs84)
|
8
|
+
# longitude : longitude in decimal degrees (wgs84)
|
9
|
+
# feature class : see http://www.geonames.org/export/codes.html, char(1)
|
10
|
+
# feature code : see http://www.geonames.org/export/codes.html, varchar(10)
|
11
|
+
# country code : ISO-3166 2-letter country code, 2 characters
|
12
|
+
# cc2 : alternate country codes, comma separated, ISO-3166 2-letter country code, 60 characters
|
13
|
+
# admin1 code : fipscode (subject to change to iso code), isocode for the us and ch, see file admin1Codes.txt for display names of this code; varchar(20)
|
14
|
+
# admin2 code : code for the second administrative division, a county in the US, see file admin2Codes.txt; varchar(80)
|
15
|
+
# admin3 code : code for third level administrative division, varchar(20)
|
16
|
+
# admin4 code : code for fourth level administrative division, varchar(20)
|
17
|
+
# population : bigint (4 byte int)
|
18
|
+
# elevation : in meters, integer
|
19
|
+
# gtopo30 : average elevation of 30'x30' (ca 900mx900m) area in meters, integer
|
20
|
+
# timezone : the timezone id (see file timeZone.txt)
|
21
|
+
# modification date : date of last modification in yyyy-MM-dd format
|
22
|
+
def self.up
|
23
|
+
create_table :geonames_features do |t|
|
24
|
+
t.integer :geonameid
|
25
|
+
t.string :name
|
26
|
+
t.string :asciiname
|
27
|
+
t.string :alternatenames
|
28
|
+
t.float :latitude
|
29
|
+
t.float :longitude
|
30
|
+
t.string :feature_class
|
31
|
+
t.string :feature
|
32
|
+
t.string :country
|
33
|
+
t.string :cc2
|
34
|
+
t.string :admin1
|
35
|
+
t.string :admin2
|
36
|
+
t.string :admin3
|
37
|
+
t.string :admin4
|
38
|
+
t.integer :population
|
39
|
+
t.integer :elevation
|
40
|
+
t.integer :gtopo30
|
41
|
+
t.string :timezone
|
42
|
+
t.timestamp :modification
|
43
|
+
t.string :type
|
44
|
+
# OPTIMIZE: create another table for all names (alternate names)
|
45
|
+
t.string :asciiname_first_letters
|
46
|
+
|
47
|
+
|
48
|
+
t.timestamps
|
49
|
+
end
|
50
|
+
|
51
|
+
add_index :geonames_features, :geonameid
|
52
|
+
add_index :geonames_features, :name
|
53
|
+
add_index :geonames_features, :asciiname
|
54
|
+
add_index :geonames_features, :country
|
55
|
+
add_index :geonames_features, :population
|
56
|
+
add_index :geonames_features, :admin1
|
57
|
+
add_index :geonames_features, :type
|
58
|
+
add_index :geonames_features, :asciiname_first_letters
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.down
|
62
|
+
drop_table :geonames_features
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
Piktur.configure do |config|
|
2
|
+
##config.public_abs_path = Rails.root.join(Rails.public_path).to_s
|
3
|
+
#config.public_abs_path = "nullll"
|
4
|
+
#config.gallery_base_path = "piktur/"
|
5
|
+
#config.thumbs_dir = "thumbs/"
|
6
|
+
|
7
|
+
#config.thumb_extension = ".jpg"
|
8
|
+
#config.image_extensions = ['jpg', 'jpeg']
|
9
|
+
##config.image_extensions = ['*']
|
10
|
+
#config.associated_extension = ".yml"
|
11
|
+
|
12
|
+
##config.thumb_file = "%{basename}-%{width}-%{height}%{extension}"
|
13
|
+
#config.thumb_file = "%{basename}-size%{size}%{extension}"
|
14
|
+
#config.associated_file = "%{basename}%{extension}"
|
15
|
+
#config.watermark_file = nil
|
16
|
+
|
17
|
+
#config.thumbs_sizes = [[140, 110], [640, 480]]
|
18
|
+
#config.param_path = :path
|
19
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module GeonamesDump
|
2
|
+
class Blocks
|
3
|
+
attr_accessor :blocks
|
4
|
+
def initialize
|
5
|
+
reset
|
6
|
+
end
|
7
|
+
|
8
|
+
def reset
|
9
|
+
self.blocks = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_block(&block)
|
13
|
+
self.blocks << block
|
14
|
+
end
|
15
|
+
|
16
|
+
def empty?
|
17
|
+
blocks.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def call_and_reset
|
21
|
+
call
|
22
|
+
reset
|
23
|
+
end
|
24
|
+
|
25
|
+
def call
|
26
|
+
blocks.each do |block|
|
27
|
+
block.call
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require "geonames_dump/version"
|
2
|
+
require "geonames_dump/blocks"
|
3
|
+
require "geonames_dump/railtie" #if defined?(Rails)
|
4
|
+
|
5
|
+
module GeonamesDump
|
6
|
+
# TODO: remove this logger
|
7
|
+
#ActiveRecord::Base.logger = Logger.new(STDOUT) if Rails.env.development? && !ENV['SILENT']
|
8
|
+
end
|
@@ -0,0 +1,257 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'ruby-progressbar'
|
3
|
+
require 'zip/zip'
|
4
|
+
require 'geonames_dump'
|
5
|
+
|
6
|
+
namespace :geonames_dump do
|
7
|
+
namespace :import do
|
8
|
+
CACHE_DIR = "#{Rails.root}/db/geonames_cache"
|
9
|
+
|
10
|
+
GEONAMES_FEATURES_COL_NAME = [
|
11
|
+
:geonameid, :name, :asciiname, :alternatenames, :latitude, :longitude, :feature_class,
|
12
|
+
:feature, :country, :cc2, :admin1, :admin2, :admin3, :admin4, :population, :elevation,
|
13
|
+
:gtopo30, :timezone, :modification
|
14
|
+
]
|
15
|
+
GEONAMES_COUNTRIES_COL_NAME = [
|
16
|
+
:iso, :iso3, :iso_numeric, :fips, :country, :capital, :area, :population, :continent,
|
17
|
+
:tld, :currency_code, :currency_name, :phone, :postal_code_format, :postal_code_regex,
|
18
|
+
:languages, :geonameid, :neighbours, :equivalent_fips_code
|
19
|
+
]
|
20
|
+
GEONAMES_ADMINS_COL_NAME = [ :code, :name, :asciiname, :geonameid ]
|
21
|
+
|
22
|
+
desc 'Prepare everything to import data'
|
23
|
+
task :prepare do
|
24
|
+
Dir::mkdir(CACHE_DIR) rescue nil
|
25
|
+
disable_logger
|
26
|
+
disable_validations if ENV['QUICK']
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'Import ALL geonames data.'
|
30
|
+
task :all => [:many, :features]
|
31
|
+
|
32
|
+
desc 'Import most of geonames data. Recommended after a clean install.'
|
33
|
+
task :many => [:prepare, :countries, :cities, :admin1, :admin2]
|
34
|
+
|
35
|
+
desc 'Import all cities, regardless of population.'
|
36
|
+
task :cities => [:prepare, :cities15000, :cities5000, :cities1000]
|
37
|
+
|
38
|
+
desc 'Import feature data. Specify Country ISO code (example : COUNTRY=FR) for just a single country. NOTE: This task can take a long time!'
|
39
|
+
task :features => [:prepare, :environment] do
|
40
|
+
download_file = ENV['COUNTRY'].present? ? ENV['COUNTRY'].upcase : 'allCountries'
|
41
|
+
zip_filename = download_file+'.zip'
|
42
|
+
|
43
|
+
txt_file = get_or_download("http://download.geonames.org/export/dump/#{zip_filename}")
|
44
|
+
|
45
|
+
# Import into the database.
|
46
|
+
File.open(txt_file) do |f|
|
47
|
+
#VALID_FEATURES = %w[ADMIN1]
|
48
|
+
#feature_attrs = VALID_FEATURES & ENV.keys
|
49
|
+
# TODO: add feature selection
|
50
|
+
insert_data(f, GEONAMES_FEATURES_COL_NAME, GeonamesCity, :title => "Features")
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# geonames:import:citiesNNN where NNN is population size.
|
55
|
+
%w[15000 5000 1000].each do |population|
|
56
|
+
desc "Import cities with population greater than #{population}"
|
57
|
+
task "cities#{population}".to_sym => [:prepare, :environment] do
|
58
|
+
|
59
|
+
txt_file = get_or_download("http://download.geonames.org/export/dump/cities#{population}.zip")
|
60
|
+
|
61
|
+
# Import into the database.
|
62
|
+
File.open(txt_file) do |f|
|
63
|
+
insert_data(f, GEONAMES_FEATURES_COL_NAME, GeonamesCity, :title => "cities of #{population}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
desc 'Import countries informations'
|
69
|
+
task :countries => :environment do
|
70
|
+
txt_file = get_or_download('http://download.geonames.org/export/dump/countryInfo.txt')
|
71
|
+
|
72
|
+
# Import into the database.
|
73
|
+
File.open(txt_file) do |f|
|
74
|
+
insert_data(f, GEONAMES_COUNTRIES_COL_NAME, GeonamesCountry, :title => "Countries")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
desc 'Import admin1 codes'
|
79
|
+
task :admin1 => [:prepare, :environment] do
|
80
|
+
txt_file = get_or_download('http://download.geonames.org/export/dump/admin1CodesASCII.txt')
|
81
|
+
|
82
|
+
# Import into the database.
|
83
|
+
File.open(txt_file) do |f|
|
84
|
+
insert_data(f, GEONAMES_ADMINS_COL_NAME, GeonamesAdmin1, :title => "Admin1 subdivisions") do |klass, attributes, col_value, idx|
|
85
|
+
col_value.gsub!('(general)', '')
|
86
|
+
col_value.strip!
|
87
|
+
if idx == 0
|
88
|
+
country, admin1 = col_value.split('.')
|
89
|
+
attributes[:country] = country.strip
|
90
|
+
attributes[:admin1] = admin1.strip rescue nil
|
91
|
+
else
|
92
|
+
attributes[GEONAMES_ADMINS_COL_NAME[idx]] = col_value
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
desc 'Import admin2 codes'
|
99
|
+
task :admin2 => [:prepare, :environment] do
|
100
|
+
txt_file = get_or_download('http://download.geonames.org/export/dump/admin2Codes.txt')
|
101
|
+
|
102
|
+
# Import into the database.
|
103
|
+
File.open(txt_file) do |f|
|
104
|
+
insert_data(f, GEONAMES_ADMINS_COL_NAME, GeonamesAdmin2, :title => "Admin2 subdivisions") do |klass, attributes, col_value, idx|
|
105
|
+
col_value.gsub!('(general)', '')
|
106
|
+
if idx == 0
|
107
|
+
country, admin1, admin2 = col_value.split('.')
|
108
|
+
attributes[:country] = country.strip
|
109
|
+
attributes[:admin1] = admin1.strip #rescue nil
|
110
|
+
attributes[:admin2] = admin2.strip #rescue nil
|
111
|
+
else
|
112
|
+
attributes[GEONAMES_ADMINS_COL_NAME[idx]] = col_value
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def disable_logger
|
121
|
+
ActiveRecord::Base.logger = Logger.new('/dev/null')
|
122
|
+
end
|
123
|
+
|
124
|
+
def disable_validations
|
125
|
+
ActiveRecord::Base.reset_callbacks(:validate)
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
def get_or_download(url, options = {})
|
130
|
+
filename = File.basename(url)
|
131
|
+
unzip = File.extname(filename) == '.zip'
|
132
|
+
txt_filename = unzip ? "#{File.basename(filename, '.zip')}.txt" : filename
|
133
|
+
txt_file_in_cache = File.join(CACHE_DIR, options[:txt_file] || txt_filename)
|
134
|
+
zip_file_in_cache = File.join(CACHE_DIR, filename)
|
135
|
+
|
136
|
+
unless File::exist?(txt_file_in_cache)
|
137
|
+
puts 'file doesn\'t exists'
|
138
|
+
if unzip
|
139
|
+
download(url, zip_file_in_cache)
|
140
|
+
unzip_file(zip_file_in_cache, CACHE_DIR)
|
141
|
+
else
|
142
|
+
download(url, txt_file_in_cache)
|
143
|
+
end
|
144
|
+
else
|
145
|
+
puts "file already exists : #{txt_file_in_cache}"
|
146
|
+
end
|
147
|
+
|
148
|
+
ret = (File::exist?(txt_file_in_cache) ? txt_file_in_cache : nil)
|
149
|
+
end
|
150
|
+
|
151
|
+
def unzip_file(file, destination)
|
152
|
+
puts "unzipping #{file}"
|
153
|
+
Zip::ZipFile.open(file) do |zip_file|
|
154
|
+
zip_file.each do |f|
|
155
|
+
f_path = File.join(destination, f.name)
|
156
|
+
FileUtils.mkdir_p(File.dirname(f_path))
|
157
|
+
zip_file.extract(f, f_path) unless File.exist?(f_path)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def download(url, output)
|
163
|
+
File.open(output, "wb") do |file|
|
164
|
+
body = fetch(url)
|
165
|
+
puts "Writing #{url} to #{output}"
|
166
|
+
file.write(body)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def fetch(url)
|
171
|
+
puts "Fetching #{url}"
|
172
|
+
url = URI.parse(url)
|
173
|
+
req = Net::HTTP::Get.new(url.path)
|
174
|
+
res = Net::HTTP.start(url.host, url.port) {|http| http.request(req)}
|
175
|
+
return res.body
|
176
|
+
end
|
177
|
+
|
178
|
+
def insert_data(file_fd, col_names, main_klass = GeonamesFeature, options = {}, &block)
|
179
|
+
# Setup nice progress output.
|
180
|
+
file_size = file_fd.stat.size
|
181
|
+
title = options[:title] || 'Feature Import'
|
182
|
+
progress_bar = ProgressBar.create(:title => title, :total => file_size, :format => '%a |%b>%i| %p%% %t')
|
183
|
+
|
184
|
+
# create block array
|
185
|
+
blocks = GeonamesDump::Blocks.new
|
186
|
+
line_counter = 0
|
187
|
+
|
188
|
+
file_fd.each_line do |line|
|
189
|
+
# prepare data
|
190
|
+
attributes = {}
|
191
|
+
klass = main_klass
|
192
|
+
|
193
|
+
# skip comments
|
194
|
+
next if line.start_with?('#')
|
195
|
+
|
196
|
+
line_counter += 1
|
197
|
+
|
198
|
+
# read values
|
199
|
+
line.strip.split("\t").each_with_index do |col_value, idx|
|
200
|
+
col = col_names[idx]
|
201
|
+
|
202
|
+
# skip leading and trailing whitespace
|
203
|
+
col_value.strip!
|
204
|
+
|
205
|
+
# block may change the type of object to create
|
206
|
+
if block_given?
|
207
|
+
yield klass, attributes, col_value, idx
|
208
|
+
else
|
209
|
+
attributes[col] = col_value
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# create or update object
|
214
|
+
#if filter?(attributes) && (block && block.call(attributes))
|
215
|
+
blocks.add_block do
|
216
|
+
if attributes.include?(:geonameid)
|
217
|
+
object = klass.where(geonameid: attributes[:geonameid]).first_or_initialize
|
218
|
+
object.update_attributes(attributes)
|
219
|
+
object.save if object.new_record? || object.changed?
|
220
|
+
else
|
221
|
+
klass.create(attributes)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# increase import speed by performing insert using transaction
|
226
|
+
if line_counter % 1000 == 0
|
227
|
+
ActiveRecord::Base.transaction do
|
228
|
+
blocks.call_and_reset
|
229
|
+
end
|
230
|
+
line_counter = 0
|
231
|
+
end
|
232
|
+
|
233
|
+
# move progress bar
|
234
|
+
progress_bar.progress = file_fd.pos
|
235
|
+
end
|
236
|
+
|
237
|
+
unless blocks.empty?
|
238
|
+
ActiveRecord::Base.transaction do
|
239
|
+
blocks.call_and_reset
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# Return true when either:
|
245
|
+
# no filter keys apply.
|
246
|
+
# all applicable filter keys include the filter value.
|
247
|
+
def filter?(attributes)
|
248
|
+
return attributes.keys.all?{|key| filter_keyvalue?(key, attributes[key])}
|
249
|
+
end
|
250
|
+
|
251
|
+
def filter_keyvalue?(col, col_value)
|
252
|
+
return true unless ENV[col.to_s]
|
253
|
+
return ENV[col.to_s].split('|').include?(col_value.to_s)
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
namespace :geonames_dump do
|
3
|
+
desc 'Run db:migrate to be up-to-date'
|
4
|
+
#task :migrate => [:environment, :copy_migrations, 'db:migrate']
|
5
|
+
task :migrate => [:environment, 'db:migrate']
|
6
|
+
|
7
|
+
# # Inspired by http://interblah.net/plugin-migrations
|
8
|
+
# desc 'Copy over the migration files and migrate'
|
9
|
+
# task :copy_migrations => :environment do
|
10
|
+
# require 'fileutils'
|
11
|
+
# APP_MIGRATION_DIR = "#{Rails.root}/db/migrate"
|
12
|
+
# PLUGIN_MIGRATION_DIR = "#{File.dirname(__FILE__)}/../../db/migrate"
|
13
|
+
#
|
14
|
+
# # Find all application migrations
|
15
|
+
# existing_migrations = Dir[APP_MIGRATION_DIR+'/*']
|
16
|
+
# existing_migrations.map!{|file| File.basename(file) =~ /^[0-9]+_(.+)$/ && $1}
|
17
|
+
#
|
18
|
+
# # Find all of this plugin's migrations
|
19
|
+
# plugin_migrations = Dir[PLUGIN_MIGRATION_DIR+'/*']
|
20
|
+
# plugin_migrations.map!{|file| File.basename(file)}
|
21
|
+
# # ... handle case when copying to plugins migrate directory.
|
22
|
+
# plugin_migrations.map!{|file| File.basename(file) =~ /^[0-9]+_(.+)$/ ? $1 : File.basename(file)}
|
23
|
+
#
|
24
|
+
# # Compare application migrations with this plugins set of migrations, and copy new migrations.
|
25
|
+
# puts 'There are no new migrations to copy.' if (plugin_migrations - existing_migrations).empty?
|
26
|
+
# base_time = Time.now
|
27
|
+
# (plugin_migrations - existing_migrations).each do |new_migration|
|
28
|
+
# migration_timestamp = base_time.strftime('%Y%m%d%H%M%S')
|
29
|
+
# puts "Copying from #{PLUGIN_MIGRATION_DIR}/#{new_migration} to #{APP_MIGRATION_DIR}/#{migration_timestamp}_#{new_migration}"
|
30
|
+
# FileUtils::cp "#{PLUGIN_MIGRATION_DIR}/#{new_migration}", "#{APP_MIGRATION_DIR}/#{migration_timestamp}_#{new_migration}"
|
31
|
+
# base_time+=1
|
32
|
+
# end
|
33
|
+
# end
|
34
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'ruby-progressbar'
|
3
|
+
require 'activerecord-reset-pk-sequence'
|
4
|
+
|
5
|
+
namespace :geonames_dump do
|
6
|
+
namespace :truncate do
|
7
|
+
|
8
|
+
desc 'Truncate all geonames data.'
|
9
|
+
#task :all => [:countries, :cities, :admin1, :admin2]
|
10
|
+
task :all => [:countries, :features]
|
11
|
+
|
12
|
+
desc 'Truncate admin1 codes'
|
13
|
+
task :admin1 => :environment do
|
14
|
+
GeonamesAdmin1.delete_all #&& GeonamesAdmin1.reset_pk_sequence
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Truncate admin2 codes'
|
18
|
+
task :admin2 => :environment do
|
19
|
+
GeonamesAdmin2.delete_all #&& GeonamesAdmin2.reset_pk_sequence
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'Truncate cities informations'
|
23
|
+
task :cities => :environment do
|
24
|
+
GeonamesCity.delete_all #&& GeonamesCity.reset_pk_sequence
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Truncate countries informations'
|
28
|
+
task :countries => :environment do
|
29
|
+
GeonamesCountry.delete_all && GeonamesCountry.reset_pk_sequence
|
30
|
+
end
|
31
|
+
|
32
|
+
desc 'Truncate features informations'
|
33
|
+
task :features => :environment do
|
34
|
+
GeonamesFeature.delete_all && GeonamesFeature.reset_pk_sequence
|
35
|
+
end
|
36
|
+
|
37
|
+
# private
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: geonames_dump
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alex Pooley
|
8
|
+
- Thomas Kienlen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-11-22 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ruby-progressbar
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '>='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: activerecord-reset-pk-sequence
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rubyzip
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
description: GeonamesDump import geographic data from geonames project into your application,
|
57
|
+
avoiding to use external service like Google Maps.
|
58
|
+
email:
|
59
|
+
- thomas.kienlen@lafourmi-immo.com
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- .gitignore
|
65
|
+
- Gemfile
|
66
|
+
- LICENSE
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- geonames_dump.gemspec
|
70
|
+
- lib/generators/geonames_dump/install_generator.rb
|
71
|
+
- lib/generators/geonames_dump/templates/app/models/geonames_admin1.rb
|
72
|
+
- lib/generators/geonames_dump/templates/app/models/geonames_admin2.rb
|
73
|
+
- lib/generators/geonames_dump/templates/app/models/geonames_city.rb
|
74
|
+
- lib/generators/geonames_dump/templates/app/models/geonames_country.rb
|
75
|
+
- lib/generators/geonames_dump/templates/app/models/geonames_feature.rb
|
76
|
+
- lib/generators/geonames_dump/templates/db/migrate/create_geonames_countries.rb
|
77
|
+
- lib/generators/geonames_dump/templates/db/migrate/create_geonames_features.rb
|
78
|
+
- lib/generators/geonames_dump/templates/piktur_config.rb
|
79
|
+
- lib/geonames_dump.rb
|
80
|
+
- lib/geonames_dump/blocks.rb
|
81
|
+
- lib/geonames_dump/railtie.rb
|
82
|
+
- lib/geonames_dump/version.rb
|
83
|
+
- lib/tasks/import.rake
|
84
|
+
- lib/tasks/install.rake
|
85
|
+
- lib/tasks/migrate.rake
|
86
|
+
- lib/tasks/truncate.rake
|
87
|
+
homepage: https://github.com/kmmndr/geonames_dump
|
88
|
+
licenses: []
|
89
|
+
metadata: {}
|
90
|
+
post_install_message:
|
91
|
+
rdoc_options: []
|
92
|
+
require_paths:
|
93
|
+
- lib
|
94
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
requirements: []
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 2.0.3
|
107
|
+
signing_key:
|
108
|
+
specification_version: 4
|
109
|
+
summary: Import data from Geonames
|
110
|
+
test_files: []
|