geonames_dump 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ .DS_Store
18
+ .*.swp
19
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in geonames.gemspec
4
+ gemspec
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,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -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,2 @@
1
+ class GeonamesAdmin1 < GeonamesFeature
2
+ end
@@ -0,0 +1,2 @@
1
+ class GeonamesAdmin2 < GeonamesFeature
2
+ end
@@ -0,0 +1,2 @@
1
+ class GeonamesCity < GeonamesFeature
2
+ 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,11 @@
1
+ #require 'rails'
2
+
3
+ module GeonamesDump
4
+ class Railtie < ::Rails::Railtie #:nodoc:
5
+ # import rake tast into rails application
6
+ rake_tasks do
7
+ Dir[File.join(File.dirname(__FILE__),'../tasks/*.rake')].each { |f| load f }
8
+ end
9
+ end
10
+ end
11
+
@@ -0,0 +1,3 @@
1
+ module GeonamesDump
2
+ VERSION = '0.0.2'
3
+ 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,4 @@
1
+ namespace :geonames_dump do
2
+ desc 'Truncate and install most of geonames data (country, admin1, admin2, cities)'
3
+ task :install => ['truncate:all', 'import:many']
4
+ 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: []