geonames_client 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --format documentation
3
+ --backtrace
4
+ --debug
data/.rvmrc ADDED
@@ -0,0 +1,2 @@
1
+ rvm use ruby-1.8.7-p334@geonames_client
2
+ rvm info
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ source "http://rubygems.org"
3
+
4
+ group :development, :test do
5
+ gem 'ruby-debug'
6
+ gem 'guard'
7
+ gem 'rb-fsevent'
8
+ gem 'growl'
9
+ gem 'guard-rspec'
10
+ gem 'guard-shell'
11
+ gem 'httparty'
12
+ end
13
+
14
+ # Specify your gem's dependencies in geonames_client.gemspec
15
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ guard 'rspec', :version => 2, :all_on_start => true, :all_after_pass => false, :cli => '--color --format doc' do
4
+ watch( %r{^spec/.+_spec\.rb$} )
5
+ watch( %r{^lib/(.+)\.rb$} ) { |m| "spec/lib/#{m[1]}_spec.rb" }
6
+ watch( 'spec/spec_helper.rb' ) { "spec" }
7
+ end
data/README.rdoc ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ task :default => :spec
@@ -0,0 +1,250 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "geonames_client/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "geonames_client"
7
+ s.version = GeonamesClient::VERSION
8
+ s.authors = ["C. Jason Harrelson"]
9
+ s.email = ["jason@lookforwardenterprises.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{A client to consume the geonames web services.}
12
+ s.description = %q{A client to consume the geonames web services (www.geonames.org).}
13
+
14
+ s.rubyforge_project = "geonames_client"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ development_dependencies = {
22
+ %q<rake> => [">= 0.9.2"],
23
+ %q<rspec> => [">= 2.6.0"],
24
+ %q<httparty> => [">= 0.8.0"]
25
+ }
26
+
27
+ runtime_dependencies = {
28
+ %q<httparty> => [">= 0.8.0"]
29
+ }
30
+
31
+ if s.respond_to? :specification_version then
32
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
33
+ s.specification_version = 3
34
+
35
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
36
+ development_dependencies.each do |name, versions|
37
+ s.add_development_dependency( name, versions )
38
+ end
39
+
40
+ runtime_dependencies.each do |name, versions|
41
+ s.add_runtime_dependency( name, versions )
42
+ end
43
+ else
44
+ development_dependencies.each do |name, versions|
45
+ s.add_dependency( name, versions )
46
+ end
47
+
48
+ runtime_dependencies.each do |name, versions|
49
+ s.add_dependency( name, versions )
50
+ end
51
+ end
52
+ else
53
+ development_dependencies.each do |name, versions|
54
+ s.add_dependency( name, versions )
55
+ end
56
+
57
+ runtime_dependencies.each do |name, versions|
58
+ s.add_dependency( name, versions )
59
+ end
60
+ end
61
+ end
62
+ # -*- encoding: utf-8 -*-
63
+ $:.push File.expand_path("../lib", __FILE__)
64
+ require "geonames_client/version"
65
+
66
+ Gem::Specification.new do |s|
67
+ s.name = "geonames_client"
68
+ s.version = GeonamesClient::VERSION
69
+ s.authors = ["C. Jason Harrelson"]
70
+ s.email = ["jason@lookforwardenterprises.com"]
71
+ s.homepage = ""
72
+ s.summary = %q{A client to consume the geonames web services.}
73
+ s.description = %q{A client to consume the geonames web services (www.geonames.org).}
74
+
75
+ s.rubyforge_project = "geonames_client"
76
+
77
+ s.files = `git ls-files`.split("\n")
78
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
79
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
80
+ s.require_paths = ["lib"]
81
+
82
+ development_dependencies = {
83
+ %q<rake> => [">= 0.9.2" ],
84
+ %q<rspec> => [">= 2.6.0" ],
85
+ %q<ruby-debug> => [">= 0.10.4"],
86
+ %q<guard> => [">= 0.4.2" ],
87
+ %q<guard-rspec> => [">= 0.4.0" ],
88
+ }
89
+
90
+ runtime_dependencies = {
91
+
92
+ }
93
+
94
+ if s.respond_to? :specification_version then
95
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
96
+ s.specification_version = 3
97
+
98
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
99
+ development_dependencies.each do |name, versions|
100
+ s.add_development_dependency( name, versions )
101
+ end
102
+
103
+ runtime_dependencies.each do |name, versions|
104
+ s.add_runtime_dependency( name, versions )
105
+ end
106
+ else
107
+ development_dependencies.each do |name, versions|
108
+ s.add_dependency( name, versions )
109
+ end
110
+
111
+ runtime_dependencies.each do |name, versions|
112
+ s.add_dependency( name, versions )
113
+ end
114
+ end
115
+ else
116
+ development_dependencies.each do |name, versions|
117
+ s.add_dependency( name, versions )
118
+ end
119
+
120
+ runtime_dependencies.each do |name, versions|
121
+ s.add_dependency( name, versions )
122
+ end
123
+ end
124
+ end
125
+ # -*- encoding: utf-8 -*-
126
+ $:.push File.expand_path("../lib", __FILE__)
127
+ require "geonames_client/version"
128
+
129
+ Gem::Specification.new do |s|
130
+ s.name = "geonames_client"
131
+ s.version = GeonamesClient::VERSION
132
+ s.authors = ["C. Jason Harrelson"]
133
+ s.email = ["jason@lookforwardenterprises.com"]
134
+ s.homepage = ""
135
+ s.summary = %q{A client to consume the geonames web services.}
136
+ s.description = %q{A client to consume the geonames web services (www.geonames.org).}
137
+
138
+ s.rubyforge_project = "geonames_client"
139
+
140
+ s.files = `git ls-files`.split("\n")
141
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
142
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
143
+ s.require_paths = ["lib"]
144
+
145
+ development_dependencies = {
146
+ %q<rake> => [">= 0.9.2" ],
147
+ %q<rspec> => [">= 2.6.0" ],
148
+ %q<ruby-debug> => [">= 0.10.4"],
149
+ %q<guard> => [">= 0.4.2" ],
150
+ %q<guard-rspec> => [">= 0.4.0" ],
151
+ }
152
+
153
+ runtime_dependencies = {
154
+
155
+ }
156
+
157
+ if s.respond_to? :specification_version then
158
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
159
+ s.specification_version = 3
160
+
161
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
162
+ development_dependencies.each do |name, versions|
163
+ s.add_development_dependency( name, versions )
164
+ end
165
+
166
+ runtime_dependencies.each do |name, versions|
167
+ s.add_runtime_dependency( name, versions )
168
+ end
169
+ else
170
+ development_dependencies.each do |name, versions|
171
+ s.add_dependency( name, versions )
172
+ end
173
+
174
+ runtime_dependencies.each do |name, versions|
175
+ s.add_dependency( name, versions )
176
+ end
177
+ end
178
+ else
179
+ development_dependencies.each do |name, versions|
180
+ s.add_dependency( name, versions )
181
+ end
182
+
183
+ runtime_dependencies.each do |name, versions|
184
+ s.add_dependency( name, versions )
185
+ end
186
+ end
187
+ end
188
+ # -*- encoding: utf-8 -*-
189
+ $:.push File.expand_path("../lib", __FILE__)
190
+ require "geonames_client/version"
191
+
192
+ Gem::Specification.new do |s|
193
+ s.name = "geonames_client"
194
+ s.version = GeonamesClient::VERSION
195
+ s.authors = ["C. Jason Harrelson"]
196
+ s.email = ["jason@lookforwardenterprises.com"]
197
+ s.homepage = ""
198
+ s.summary = %q{A client to consume the geonames web services.}
199
+ s.description = %q{A client to consume the geonames web services (www.geonames.org).}
200
+
201
+ s.rubyforge_project = "geonames_client"
202
+
203
+ s.files = `git ls-files`.split("\n")
204
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
205
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
206
+ s.require_paths = ["lib"]
207
+
208
+ development_dependencies = {
209
+ %q<rake> => [">= 0.9.2" ],
210
+ %q<rspec> => [">= 2.6.0" ],
211
+ %q<ruby-debug> => [">= 0.10.4"],
212
+ %q<guard> => [">= 0.4.2" ],
213
+ %q<guard-rspec> => [">= 0.4.0" ],
214
+ }
215
+
216
+ runtime_dependencies = {
217
+
218
+ }
219
+
220
+ if s.respond_to? :specification_version then
221
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
222
+ s.specification_version = 3
223
+
224
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
225
+ development_dependencies.each do |name, versions|
226
+ s.add_development_dependency( name, versions )
227
+ end
228
+
229
+ runtime_dependencies.each do |name, versions|
230
+ s.add_runtime_dependency( name, versions )
231
+ end
232
+ else
233
+ development_dependencies.each do |name, versions|
234
+ s.add_dependency( name, versions )
235
+ end
236
+
237
+ runtime_dependencies.each do |name, versions|
238
+ s.add_dependency( name, versions )
239
+ end
240
+ end
241
+ else
242
+ development_dependencies.each do |name, versions|
243
+ s.add_dependency( name, versions )
244
+ end
245
+
246
+ runtime_dependencies.each do |name, versions|
247
+ s.add_dependency( name, versions )
248
+ end
249
+ end
250
+ end
@@ -0,0 +1,68 @@
1
+ class Location
2
+
3
+ def self.deg2rad(deg)
4
+ (deg * Math::PI / 180)
5
+ end
6
+
7
+ def self.rad2deg(rad)
8
+ (rad * 180 / Math::PI)
9
+ end
10
+
11
+ def self.acos(rad)
12
+ Math.atan2(Math.sqrt(1 - rad**2), rad)
13
+ end
14
+
15
+ def self.distance_in_miles(loc1, loc2)
16
+ lat1 = loc1.latitude
17
+ lon1 = loc1.longitude
18
+ lat2 = loc2.latitude
19
+ lon2 = loc2.longitude
20
+ theta = lon1 - lon2
21
+
22
+ dist = Math.sin(self.deg2rad(lat1)) * Math.sin(deg2rad(lat2))
23
+ + Math.cos(self.deg2rad(lat1)) * Math.cos(self.deg2rad(lat2)) * Math.cos(deg2rad(theta))
24
+
25
+ dist = self.rad2deg(self.acos(dist))
26
+
27
+ (dist * 60 * 1.1515).round #distance in miles
28
+ end
29
+
30
+ def miles_to(location)
31
+ Location.distance_in_miles(self, location)
32
+ end
33
+
34
+ def self.locationArea(location, miles)
35
+ radius = miles.to_f
36
+ latR = radius / ((6076 / 5280) * 60)
37
+ lonR = radius / (((Math.cos(location.latitude * Math::PI / 180) * 6076) / 5280) * 60)
38
+
39
+ {
40
+ :min_latitude => location.latitude - latR,
41
+ :min_longitude => location.longitude - lonR,
42
+ :max_latitude => location.latitude + latR,
43
+ :max_longitude => location.longitude + lonR
44
+ }
45
+ end
46
+
47
+ def self.location_ids_in_range(location, miles)
48
+ la = Location.locationArea(location, miles)
49
+ Location.find(:all,
50
+ :select => Location.connection.quote_column_name( 'id' ),
51
+ :conditions => ["(#{connection.quote_table_name 'locations'}.#{connection.quote_column_name 'latitude'} <= ?) AND (#{connection.quote_table_name 'locations'}.#{connection.quote_column_name 'latitude'} >= ?) AND " +
52
+ "(#{connection.quote_table_name 'locations'}.#{connection.quote_column_name 'longitude'} >= ?) AND (#{connection.quote_table_name 'locations'}.#{connection.quote_column_name 'longitude'} <= ?)",
53
+ la[:max_latitude], la[:min_latitude], la[:min_longitude], la[:max_longitude]
54
+ ]
55
+ ).collect { |l| l.id }
56
+ end
57
+
58
+ def self.locations_in_range(location, miles)
59
+ la = Location.locationArea(location, miles)
60
+ Location.find(:all,
61
+ :conditions => ["(#{connection.quote_table_name 'locations'}.#{connection.quote_column_name 'latitude'} <= ?) AND (#{connection.quote_table_name 'locations'}.#{connection.quote_column_name 'latitude'} >= ?) AND " +
62
+ "(#{connection.quote_table_name 'locations'}.#{connection.quote_column_name 'longitude'} >= ?) AND (#{connection.quote_table_name 'locations'}.#{connection.quote_column_name 'longitude'} <= ?)",
63
+ la[:max_latitude], la[:min_latitude], la[:min_longitude], la[:max_longitude]
64
+ ]
65
+ )
66
+ end
67
+
68
+ end
@@ -0,0 +1,123 @@
1
+ module GeonamesClient
2
+ # This class is not suitable for distances over a couple of miles. Due to the fact
3
+ # that spherical triginometry must be employed due to the curvature of the earth.
4
+ #
5
+ class Location
6
+
7
+ attr_reader :latitude_in_decimal_degrees, :longitude_in_decimal_degrees
8
+
9
+ def initialize( latitude_in_decimal_degrees,
10
+ longitude_in_decimal_degrees )
11
+ @latitude_in_decimal_degrees = latitude_in_decimal_degrees
12
+ @longitude_in_decimal_degrees = longitude_in_decimal_degrees
13
+ end
14
+
15
+ def bounding_box_locations_as_array( distance )
16
+ bounding_box_locations( distance ).map &:to_a
17
+ end
18
+
19
+ def bounding_box_locations_as_hash_like_array( distance )
20
+ [
21
+ :northeast,
22
+ :northwest,
23
+ :southwest,
24
+ :southeast
25
+ ].zip( bounding_box_locations_as_array( distance ) )
26
+ end
27
+
28
+ def bounding_box_locations_as_hash( distance )
29
+ hash = {}
30
+
31
+ bounding_box_locations_as_hash_like_array( distance ).each do |direction, location|
32
+ hash[direction] = location
33
+ end
34
+
35
+ hash
36
+ end
37
+
38
+ def bounding_box_locations( distance )
39
+ %w(
40
+ northeast
41
+ northwest
42
+ southwest
43
+ southeast
44
+ ).map do |direction|
45
+ send( "bounding_box_#{direction}_location", distance )
46
+ end
47
+ end
48
+
49
+ def to_a
50
+ [
51
+ latitude_in_decimal_degrees,
52
+ longitude_in_decimal_degrees
53
+ ]
54
+ end
55
+
56
+ def ==( another_location )
57
+ return false unless another_location.is_a?( Location )
58
+ return false unless another_location.latitude_in_decimal_degrees == latitude_in_decimal_degrees
59
+ return false unless another_location.longitude_in_decimal_degrees == longitude_in_decimal_degrees
60
+
61
+ true
62
+ end
63
+
64
+ private
65
+
66
+ %w(
67
+ northeast
68
+ northwest
69
+ southwest
70
+ southeast
71
+ ).each do |direction|
72
+
73
+ define_method "dx_#{direction}" do |distance|
74
+ rount_float( distance * Math.cos( send( "#{direction}_theta" ).degrees ), 2 )
75
+ end
76
+
77
+ define_method "dy_#{direction}" do |distance|
78
+ rount_float( distance * Math.sin( send( "#{direction}_theta" ).degrees ), 2 )
79
+ end
80
+
81
+ define_method "delta_latitude_#{direction}" do |distance|
82
+ rount_float( send( "dy_#{direction}", distance ) / 110540.0, 6 )
83
+ end
84
+
85
+ define_method "delta_longitude_#{direction}" do |distance|
86
+ rount_float( send( "dx_#{direction}", distance ) / (111320.0 * Math.cos( latitude_in_decimal_degrees.degrees )), 6 )
87
+ end
88
+
89
+ define_method "latitude_#{direction}" do |distance|
90
+ rount_float( latitude_in_decimal_degrees + send( "delta_latitude_#{direction}", distance ), 6 )
91
+ end
92
+
93
+ define_method "longitude_#{direction}" do |distance|
94
+ rount_float( longitude_in_decimal_degrees + send( "delta_longitude_#{direction}", distance ), 6 )
95
+ end
96
+
97
+ define_method "bounding_box_#{direction}_location" do |distance|
98
+ Location.new send( "latitude_#{direction}", distance ),
99
+ send( "longitude_#{direction}", distance )
100
+ end
101
+
102
+ end
103
+
104
+ # Measuring theta from due east.
105
+ {
106
+ :northeast => 45,
107
+ :northwest => 135,
108
+ :southwest => 225,
109
+ :southeast => 315
110
+ }.each do |direction, value|
111
+
112
+ define_method "#{direction}_theta" do
113
+ value
114
+ end
115
+
116
+ end
117
+
118
+ def rount_float( val, precision )
119
+ sprintf( "%.#{precision}f", val ).to_f
120
+ end
121
+
122
+ end
123
+ end
@@ -0,0 +1,29 @@
1
+ module GeonamesClient
2
+ class NearbyStreet
3
+
4
+ attr_reader :name
5
+
6
+ def initialize( options )
7
+ @name = options[:name]
8
+ end
9
+
10
+ def self.all( *names )
11
+ names.map { |name| NearbyStreet.new( :name => name ) }
12
+ end
13
+
14
+ def ==( another_nearby_street )
15
+ return false unless another_nearby_street.is_a?( NearbyStreet )
16
+ return false unless another_nearby_street.name == name
17
+
18
+ true
19
+ end
20
+
21
+ def <=>( another_nearby_street )
22
+ return -1 if name < another_nearby_street.name
23
+ return 1 if name > another_nearby_street.name
24
+
25
+ 0
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,96 @@
1
+ require 'httparty'
2
+
3
+ module GeonamesClient
4
+ class Service
5
+
6
+ include HTTParty
7
+
8
+ base_uri ServiceDefinition.address
9
+
10
+ attr_reader :api_key
11
+
12
+ def initialize( api_key )
13
+ @api_key = api_key
14
+ end
15
+
16
+ def service_definition
17
+ @service_definition ||= ServiceDefinition.new
18
+ end
19
+
20
+ def get_nearby_streets( options )
21
+ options.merge!( :username => api_key )
22
+
23
+ NearbyStreet.all *nearby_streets( options ).sort
24
+ end
25
+
26
+ def get_nearby_streets_within_radius( options )
27
+ options.merge!( :username => api_key )
28
+
29
+ street_names = (nearby_streets( options ) +
30
+ nearby_streets_northeast( options ) +
31
+ nearby_streets_northwest( options ) +
32
+ nearby_streets_southeast( options ) +
33
+ nearby_streets_southwest( options ) ).uniq
34
+
35
+
36
+ NearbyStreet.all *street_names.sort
37
+ end
38
+
39
+ def nearby_streets( options )
40
+ uri = service_definition.full_nearby_streets_uri( options )
41
+
42
+ response = self.class.get( uri )
43
+
44
+ check_response_for_error( response )
45
+
46
+ response.parsed_response['geonames']['streetSegment'].map { |s| s['name'] }.uniq.compact
47
+ end
48
+
49
+ def check_response_for_error( response )
50
+ geonames = response['geonames']
51
+ return unless geonames
52
+ error = geonames['status']
53
+
54
+ unless error.nil?
55
+ raise "Geonames returned error: (#{error['value']}) #{error['message']}"
56
+ end
57
+ end
58
+
59
+ %w(
60
+ northeast
61
+ northwest
62
+ southwest
63
+ southeast
64
+ ).each do |direction|
65
+
66
+ define_method "nearby_streets_#{direction}" do |options|
67
+ location = bounding_box( options )[direction.to_sym]
68
+ lat = location.first
69
+ long = location.last
70
+
71
+ uri = service_definition.full_nearby_streets_uri( :latitude => lat,
72
+ :longitude => long,
73
+ :username => api_key )
74
+
75
+ response = self.class.get( uri )
76
+
77
+ check_response_for_error( response )
78
+ geonames = response.parsed_response['geonames']
79
+ geonames.nil? ? [] : response.parsed_response['geonames']['streetSegment'].map { |s| s['name'] }.uniq.compact
80
+ end
81
+
82
+ end
83
+
84
+ def bounding_box( options )
85
+ location = Location.new( options[:latitude].to_f,
86
+ options[:longitude].to_f )
87
+
88
+ location.bounding_box_locations_as_hash( options[:radius] || default_radius )
89
+ end
90
+
91
+ def default_radius
92
+ 402
93
+ end
94
+
95
+ end
96
+ end
@@ -0,0 +1,76 @@
1
+ module GeonamesClient
2
+ class ServiceDefinition
3
+
4
+ def self.address
5
+ 'api.geonames.org'
6
+ end
7
+
8
+ def base_uri
9
+ ['http://', self.class.address].join
10
+ end
11
+
12
+ def nearby_streets_path
13
+ '/findNearbyStreets'
14
+ end
15
+
16
+ def nearby_streets_json_path
17
+ '/findNearbyStreetsJSON'
18
+ end
19
+
20
+ def latitude_parameter
21
+ 'lat'
22
+ end
23
+
24
+ def longitude_parameter
25
+ 'lng'
26
+ end
27
+
28
+ def username_parameter
29
+ 'username'
30
+ end
31
+
32
+ def nearby_streets_base_path( format=:xml )
33
+ format = format.to_sym
34
+
35
+ raise "Invalid format: expected one of #{available_formats.join( ', ' )}" unless available_formats.include?( format )
36
+
37
+ return [base_uri,
38
+ format == :xml ? nearby_streets_path : nearby_streets_json_path].join ''
39
+ end
40
+
41
+ def full_nearby_streets_uri( params={} )
42
+ expected_parameters.each do |p|
43
+ raise "Please provide the :#{p} parameter" unless params.has_key?( p.to_sym )
44
+ end
45
+
46
+ format = params.delete( :format ) || default_format
47
+
48
+ [nearby_streets_base_path( format ), query_string( params )].join '?'
49
+ end
50
+
51
+ private
52
+
53
+ def default_format
54
+ :xml
55
+ end
56
+
57
+ def available_formats
58
+ [:xml, :json]
59
+ end
60
+
61
+ def expected_parameters
62
+ %w(
63
+ latitude
64
+ longitude
65
+ username
66
+ )
67
+ end
68
+
69
+ def query_string( params )
70
+ expected_parameters.map do |p|
71
+ [send( "#{p}_parameter" ), params[p.to_sym]].join '='
72
+ end.join '&'
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,3 @@
1
+ module GeonamesClient
2
+ VERSION = "1.0.0"
3
+ end