earth 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. data/CHANGELOG +6 -0
  2. data/Rakefile +0 -3
  3. data/TODO +1 -1
  4. data/ar17.html +2093 -0
  5. data/data/air/aircraft.csv +7 -0
  6. data/data/air/airports.csv +1 -0
  7. data/earth.gemspec +4 -3
  8. data/errata/airline/bts_carrier_codes_errata.csv +74 -10
  9. data/errata/airport/openflights_errata.csv +7 -0
  10. data/errata/flight_segment/bts_errata.csv +1 -0
  11. data/lib/earth/air/aircraft.rb +1 -1
  12. data/lib/earth/air/aircraft/data_miner.rb +1 -1
  13. data/lib/earth/air/airline.rb +1 -1
  14. data/lib/earth/air/airline/data_miner.rb +6 -10
  15. data/lib/earth/air/airport.rb +6 -6
  16. data/lib/earth/air/bts_aircraft.rb +1 -1
  17. data/lib/earth/air/flight_segment.rb +1 -1
  18. data/lib/earth/automobile/automobile_activity_year_type.rb +1 -1
  19. data/lib/earth/automobile/automobile_activity_year_type_fuel/data_miner.rb +3 -3
  20. data/lib/earth/automobile/automobile_make_model_year_variant.rb +2 -2
  21. data/lib/earth/automobile/automobile_make_model_year_variant/data_miner.rb +1 -1
  22. data/lib/earth/automobile/automobile_type_fuel_year.rb +1 -1
  23. data/lib/earth/automobile/automobile_type_fuel_year/data_miner.rb +2 -2
  24. data/lib/earth/automobile/automobile_type_fuel_year_control.rb +1 -1
  25. data/lib/earth/insolation_scopes.rb +10 -0
  26. data/lib/earth/loader.rb +0 -7
  27. data/lib/earth/locality/climate_division.rb +3 -3
  28. data/lib/earth/locality/climate_division_month.rb +28 -0
  29. data/lib/earth/locality/climate_division_month/data_miner.rb +140 -0
  30. data/lib/earth/locality/direct_normal_insolation.rb +37 -0
  31. data/lib/earth/locality/direct_normal_insolation/data_miner.rb +41 -0
  32. data/lib/earth/locality/egrid_subregion.rb +4 -1
  33. data/lib/earth/locality/electricity_mix.rb +9 -1
  34. data/lib/earth/locality/global_horizontal_insolation.rb +37 -0
  35. data/lib/earth/locality/global_horizontal_insolation/data_miner.rb +41 -0
  36. data/lib/earth/locality/photovoltaic_insolation.rb +37 -0
  37. data/lib/earth/locality/photovoltaic_insolation/data_miner.rb +41 -0
  38. data/lib/earth/locality/zip_code.rb +9 -15
  39. data/lib/earth/residence/residence_fuel_price.rb +1 -1
  40. data/lib/earth/tasks.rb +5 -0
  41. data/lib/earth/version.rb +1 -1
  42. data/spec/data_mining_spec.rb +1 -1
  43. data/spec/earth/air/aircraft_spec.rb +2 -2
  44. data/spec/earth/air/airline_spec.rb +1 -1
  45. data/spec/earth/air/airport_spec.rb +1 -1
  46. data/spec/earth/air/bts_aircraft_spec.rb +1 -1
  47. data/spec/earth/air/flight_segment_spec.rb +19 -21
  48. data/spec/earth/automobile/automobile_make_model_year_variant_spec.rb +1 -1
  49. data/spec/earth/locality/climate_division_month_spec.rb +23 -0
  50. data/spec/earth/locality/direct_normal_insolation_spec.rb +8 -0
  51. data/spec/earth/locality/global_horizontal_insolation_spec.rb +8 -0
  52. data/spec/earth/locality/photovoltaic_insolation_spec.rb +8 -0
  53. data/spec/earth/locality/zip_code_spec.rb +1 -10
  54. data/spec/earth_spec.rb +1 -1
  55. data/spec/spec_helper.rb +1 -1
  56. metadata +261 -410
  57. data/data/air/airlines.csv +0 -45
  58. data/vendor/geokit-rails/.gitignore +0 -2
  59. data/vendor/geokit-rails/CHANGELOG.rdoc +0 -49
  60. data/vendor/geokit-rails/MIT-LICENSE +0 -20
  61. data/vendor/geokit-rails/README.markdown +0 -569
  62. data/vendor/geokit-rails/Rakefile +0 -18
  63. data/vendor/geokit-rails/about.yml +0 -11
  64. data/vendor/geokit-rails/assets/api_keys_template +0 -61
  65. data/vendor/geokit-rails/init.rb +0 -2
  66. data/vendor/geokit-rails/install.rb +0 -14
  67. data/vendor/geokit-rails/lib/geokit-rails.rb +0 -28
  68. data/vendor/geokit-rails/lib/geokit-rails/acts_as_mappable.rb +0 -469
  69. data/vendor/geokit-rails/lib/geokit-rails/adapters/abstract.rb +0 -31
  70. data/vendor/geokit-rails/lib/geokit-rails/adapters/mysql.rb +0 -22
  71. data/vendor/geokit-rails/lib/geokit-rails/adapters/mysql2.rb +0 -22
  72. data/vendor/geokit-rails/lib/geokit-rails/adapters/postgresql.rb +0 -22
  73. data/vendor/geokit-rails/lib/geokit-rails/adapters/sqlserver.rb +0 -43
  74. data/vendor/geokit-rails/lib/geokit-rails/defaults.rb +0 -22
  75. data/vendor/geokit-rails/lib/geokit-rails/geocoder_control.rb +0 -16
  76. data/vendor/geokit-rails/lib/geokit-rails/ip_geocode_lookup.rb +0 -46
  77. data/vendor/geokit-rails/test/acts_as_mappable_test.rb +0 -474
  78. data/vendor/geokit-rails/test/boot.rb +0 -25
  79. data/vendor/geokit-rails/test/database.yml +0 -25
  80. data/vendor/geokit-rails/test/fixtures/companies.yml +0 -7
  81. data/vendor/geokit-rails/test/fixtures/custom_locations.yml +0 -54
  82. data/vendor/geokit-rails/test/fixtures/locations.yml +0 -54
  83. data/vendor/geokit-rails/test/fixtures/mock_addresses.yml +0 -17
  84. data/vendor/geokit-rails/test/fixtures/mock_families.yml +0 -2
  85. data/vendor/geokit-rails/test/fixtures/mock_houses.yml +0 -9
  86. data/vendor/geokit-rails/test/fixtures/mock_organizations.yml +0 -5
  87. data/vendor/geokit-rails/test/fixtures/mock_people.yml +0 -5
  88. data/vendor/geokit-rails/test/fixtures/stores.yml +0 -0
  89. data/vendor/geokit-rails/test/ip_geocode_lookup_test.rb +0 -77
  90. data/vendor/geokit-rails/test/models/company.rb +0 -3
  91. data/vendor/geokit-rails/test/models/custom_location.rb +0 -12
  92. data/vendor/geokit-rails/test/models/location.rb +0 -4
  93. data/vendor/geokit-rails/test/models/mock_address.rb +0 -4
  94. data/vendor/geokit-rails/test/models/mock_family.rb +0 -3
  95. data/vendor/geokit-rails/test/models/mock_house.rb +0 -3
  96. data/vendor/geokit-rails/test/models/mock_organization.rb +0 -4
  97. data/vendor/geokit-rails/test/models/mock_person.rb +0 -4
  98. data/vendor/geokit-rails/test/models/store.rb +0 -3
  99. data/vendor/geokit-rails/test/schema.rb +0 -60
  100. data/vendor/geokit-rails/test/tasks.rake +0 -31
  101. data/vendor/geokit-rails/test/test_helper.rb +0 -23
@@ -1,45 +0,0 @@
1
- name,secondary_name,icao_code,icao_code_source,iata_code,iata_code_source,notes
2
- ABSA Cargo,,TUS,Wikipedia,M3,IATA
3
- ABX Air,,ABX,Wikipedia,GB,IATA
4
- AeroSucre,,KRE,Wikipedia,6N,IATA
5
- Air Hong Kong,,AHK,Wikipedia,LD,IATA
6
- Air Slovakia,,SVK,Wikipedia,GM,IATA
7
- Air Tanzania,,ATC,Wikipedia,TC,IATA
8
- Airlift International,,LFM,ICAO
9
- Amerijet International,,AJT,Wikipedia,M6,IATA
10
- Arrow Cargo,,APW,Wikipedia,JW,IATA
11
- BA Connect,,BRT,Wikipedia
12
- Baboo,,BBO,Wikipedia,F7,IATA
13
- Bluebird Cargo,,BBD,Wikipedia,BF,IATA
14
- China Cargo Airlines,,CKK,Wikipedia,CK,IATA
15
- China Postal Airlines,,CYZ,Wikipedia,8Y,IATA
16
- Domodedovo Airlines,,DMO,Wikipedia,E3,IATA
17
- Eurojet Romania,,RDP,Wikipedia
18
- FedEx,,FDX,Wikipedia,FX,IATA
19
- Florida West Airlines,,FWL,Wikipedia,RF,IATA
20
- GB Airways,,GBL,Wikipedia,GT,IATA
21
- Grandstar Cargo,,GSC,Wikipedia,GD,IATA
22
- Great Wall Airlines,,GWL,Wikipedia,IJ,IATA
23
- Highland Airways,,HWY,Wikipedia,8H,IATA
24
- Itek Air,,IKA,Wikipedia,GI,IATA
25
- Jade Cargo International,,JAE,Wikipedia,JI,IATA
26
- KrasAir,,KJC,Wikipedia,7B,IATA
27
- MAT,Macedonian Airlines,MAK,Wikipedia,IN,IATA
28
- Mexicana,,MXA,Wikipedia,MX,IATA
29
- MIA Airlines,,JLA,Wikipedia
30
- NCA,Nippon Cargo Airlines,NCA,Wikipedia,KZ,IATA
31
- Northwest Airlines,,NWA,Wikipedia,NW,IATA
32
- Polar Air Cargo,,PAC,Wikipedia,PO,IATA
33
- Romavia,,RMV,Wikipedia,WQ,IATA
34
- SAM,,SAM,ICAO,,,subsidiary of Avianca
35
- Shanghai Airlines Cargo,,SHQ,Wikipedia,F4,IATA
36
- Shenzhen Donghai Airlines,,EPA,Wikipedia
37
- Silverjet,,FJE,Wikipedia
38
- SkyEurope,,ESK,Wikipedia,NE,IATA
39
- Tavria-Mak,,TVM,Wikipedia
40
- Tiriac Air,,TIH,Wikipedia
41
- UPS,,UPS,Wikipedia,5X,IATA
42
- Varig,,VRG,Wikipedia,RG,IATA
43
- VarigLog,,VLO,Wikipedia
44
- Yangtze River Express,,YZR,Wikipedia,Y8,IATA
45
- Zoom Airlines,,UKZ,Wikipedia
@@ -1,2 +0,0 @@
1
- test/*-debug.log
2
- .svn
@@ -1,49 +0,0 @@
1
- == 2011-04-03 / Version 1.1.5
2
- * Added mysql2 adapter support backported from geokit-rails3.
3
-
4
- == 2009-10-02 / Version 1.2.0
5
- * Overhaul the test suite to be independent of a Rails project
6
- * Added concept of database adapter. Ported mysql/postgresql conditional code to their own adapter.
7
- * Added SQL Server support. THANKS http://github.com/brennandunn for all the improvements in this release
8
-
9
- == 2009-09-26 / Version 1.1.3
10
- * documentation updates and updated to work with Geokit gem v1.5.0
11
- * IMPORTANT: in the Geokit gem, Geokit::Geocoders::timeout became Geokit::Geocoders::request_timeout for jruby compatibility.
12
- The plugin sets this in config/initializers/geokit_config.rb. So if you've upgraded the gem to 1.5.0, you need to
13
- make the change manually from Geokit::Geocoders::timeout to Geokit::Geocoders::request_timeout in config/initializers/geokit_config.rb
14
-
15
- == 2009-06-08 / Version 1.1.2
16
- * Added support for hashes in :through. So you can do: acts_as_mappable :through => { :state => :country } (Thanks José Valim).
17
-
18
- == 2009-05-22 / Version 1.1.1
19
- * Support for multiple ip geocoders (Thanks dreamcat4)
20
- * Now checks if either :origin OR :bounds is passed, and proceeds with geokit query if this is true (Thanks Glenn Powell)
21
- * Raises a helpful error if someone uses through but the association does not exists or was not defined yet (Thanks José Valim)
22
-
23
- == 2009-04-11 / Version 1.1.0
24
- * Fixed :through usages so that the through model is only included in the query if there
25
- is an :origin passed in (Only if it is a geokit search) (Thanks Glenn Powell)
26
- * Move library initialisation into lib/geokit-rails. init.rb uses lib/geokit-rails now (thanks Alban Peignier)
27
- * Handle the case where a user passes a hash to the :conditions Finder option (thanks Adam Greene)
28
- * Added ability to specify domain-specific API keys (Thanks Glenn Powell)
29
-
30
- == 2009-02-20
31
- * More powerful assosciations in the Rails Plugin:You can now specify a model as mappable "through" an associated model.
32
- In other words, that associated model is the actual mappable model with "lat" and "lng" attributes, but this "through" model
33
- can still utilize all Geokit's "find by distance" finders. Also Rails 2.3 compatibility (thanks github/glennpow)
34
-
35
- == 2008-12-18
36
- * Split Rails plugin from geocoder gem
37
- * updated for Rails 2.2.2
38
-
39
- == 2008-08-20
40
- * Further fix of distance calculation, this time in SQL. Now uses least() function, which is available in MySQL version 3.22.5+ and postgres versions 8.1+
41
-
42
- == 2008-01-16
43
- * fixed the "zero-distance" bug (calculating between two points that are the same)
44
-
45
- == 2007-11-12
46
- * fixed a small but with queries crossing meridian, and also fixed find(:closest)
47
-
48
- == 2007-10-11
49
- * Fixed Rails2/Edge compatability
@@ -1,20 +0,0 @@
1
- Copyright (c) 2007 Bill Eisenhauer & Andre Lewis
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining
4
- a copy of this software and associated documentation files (the
5
- "Software"), to deal in the Software without restriction, including
6
- without limitation the rights to use, copy, modify, merge, publish,
7
- distribute, sublicense, and/or sell copies of the Software, and to
8
- permit persons to whom the Software is furnished to do so, subject to
9
- the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be
12
- included in all copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,569 +0,0 @@
1
- ## WHAT IS THIS?
2
-
3
- It's geokit-rails for Rails 2.x with added mysql2 support. That's it.
4
-
5
- Mysql2 support has been backported from Jérémy Lecour's work on [geokit-rails3](https://github.com/jlecour/geokit-rails3).
6
-
7
- I confess to not having run the bundled tests against this, but it seems to work exactly how you'd expect, and is working great in a large production application. If you're a Geokit developer and want to let me know whether the tests pass I'd appreciate it.
8
-
9
- ## INSTALLATION
10
-
11
- Geokit consists of a Gem ([geokit-gem](http://github.com/andre/geokit-gem/tree/master)) and a Rails plugin ([geokit-rails](http://github.com/niralisse/geokit-rails-mysql2/tree/master)).
12
-
13
- #### 1. Install the Rails plugin:
14
-
15
- cd [YOUR_RAILS_APP_ROOT]
16
- script/plugin install git://github.com/niralisse/geokit-rails-mysql2.git
17
-
18
- #### 2. Add this line to your environment.rb
19
- (inside the Rails::Initializer.run do |config| block)
20
-
21
- config.gem "geokit"
22
-
23
- This informs Rails of the gem dependency.
24
-
25
- #### 3. Tell Rails to install the gem:
26
-
27
- rake gems:install
28
-
29
- And you're good to go! If you're running an older verion of Rails, just install the gem manually: `sudo gem install rails`
30
-
31
- ## FEATURE SUMMARY
32
-
33
- Geokit provides key functionality for location-oriented Rails applications:
34
-
35
- - Distance calculations, for both flat and spherical environments. For example,
36
- given the location of two points on the earth, you can calculate the miles/KM
37
- between them.
38
- - ActiveRecord distance-based finders. For example, you can find all the points
39
- in your database within a 50-mile radius.
40
- - IP-based location lookup utilizing hostip.info. Provide an IP address, and get
41
- city name and latitude/longitude in return
42
- - A before_filter helper to geocoder the user's location based on IP address,
43
- and retain the location in a cookie.
44
- - Geocoding from multiple providers. It provides a fail-over mechanism, in case
45
- your input fails to geocode in one service. Geocoding is provided buy the Geokit
46
- gem, which you must have installed
47
-
48
- The goal of this plugin is to provide the common functionality for location-oriented
49
- applications (geocoding, location lookup, distance calculation) in an easy-to-use
50
- package.
51
-
52
- ## A NOTE ON TERMINOLOGY
53
-
54
- Throughout the code and API, latitude and longitude are referred to as lat
55
- and lng. We've found over the long term the abbreviation saves lots of typing time.
56
-
57
- ## LOCATION QUERIES
58
-
59
- To get started, just specify an ActiveRecord class as `acts_as_mappale`:
60
-
61
- class Location < ActiveRecord::Base
62
- acts_as_mappable
63
- end
64
-
65
- There are some defaults you can override:
66
-
67
- class Location < ActiveRecord::Base
68
- acts_as_mappable :default_units => :miles,
69
- :default_formula => :sphere,
70
- :distance_field_name => :distance,
71
- :lat_column_name => :lat,
72
- :lng_column_name => :lng
73
- end
74
-
75
-
76
- The optional parameters are :units, :formula, and distance_field_name.
77
- Values for :units can be :miles, :kms (kilometers), or :nms (nautical miles),
78
- with :miles as the default. Values for :formula can be :sphere or :flat with
79
- :sphere as the default. :sphere gives you Haversine calculations, while :flat
80
- gives the Pythagorean Theory. These defaults persist through out the plug-in.
81
-
82
- The plug-in creates a calculated `distance` field on AR instances that have
83
- been retrieved throw a Geokit location query. By default, these fields are
84
- known as "distance" but this can be changed through the `:distance_field_name` key.
85
-
86
- You can also define alternative column names for latitude and longitude using
87
- the `:lat_column_name` and `:lng_column_name` keys. The defaults are 'lat' and
88
- 'lng' respectively.
89
-
90
- Once you've specified acts_as_mappable, a set of distance-based
91
- finder methods are available:
92
-
93
- Origin as a two-element array of latititude/longitude:
94
-
95
- find(:all, :origin => [37.792,-122.393])
96
-
97
- Origin as a geocodeable string:
98
-
99
- find(:all, :origin => '100 Spear st, San Francisco, CA')
100
-
101
- Origin as an object which responds to lat and lng methods,
102
- or latitude and longitude methods, or whatever methods you have
103
- specified for `lng_column_name` and `lat_column_name`:
104
-
105
- find(:all, :origin=>my_store) # my_store.lat and my_store.lng methods exist
106
-
107
- Often you will need to find within a certain distance. The prefered syntax is:
108
-
109
- find(:all, :origin => @somewhere, :within => 5)
110
-
111
- . . . however these syntaxes will also work:
112
-
113
- find_within(5, :origin => @somewhere)
114
- find(:all, :origin => @somewhere, :conditions => "distance < 5")
115
-
116
- Note however that the third form should be avoided. With either of the first two,
117
- Geokit automatically adds a bounding box to speed up the radial query in the database.
118
- With the third form, it does not.
119
-
120
- If you need to combine distance conditions with other conditions, you should do
121
- so like this:
122
-
123
- find(:all, :origin => @somewhere, :within => 5, :conditions=>['state=?',state])
124
-
125
- If :origin is not provided in the finder call, the find method
126
- works as normal. Further, the key is removed
127
- from the :options hash prior to invoking the superclass behavior.
128
-
129
- Other convenience methods work intuitively and are as follows:
130
-
131
- find_within(distance, :origin => @somewhere)
132
- find_beyond(distance, :origin => @somewhere)
133
- find_closest(:origin => @somewhere)
134
- find_farthest(:origin => @somewhere)
135
-
136
- where the options respect the defaults, but can be overridden if
137
- desired.
138
-
139
- Lastly, if all that is desired is the raw SQL for distance
140
- calculations, you can use the following:
141
-
142
- distance_sql(origin, units=default_units, formula=default_formula)
143
-
144
- Thereafter, you are free to use it in find_by_sql as you wish.
145
-
146
- There are methods available to enable you to get the count based upon
147
- the find condition that you have provided. These all work similarly to
148
- the finders. So for instance:
149
-
150
- count(:origin, :conditions => "distance < 5")
151
- count_within(distance, :origin => @somewhere)
152
- count_beyond(distance, :origin => @somewhere)
153
-
154
- ## FINDING WITHIN A BOUNDING BOX
155
-
156
- If you are displaying points on a map, you probably need to query for whatever falls within the rectangular bounds of the map:
157
-
158
- Store.find :all, :bounds=>[sw_point,ne_point]
159
-
160
- The input to :bounds can be array with the two points or a Bounds object. However you provide them, the order should always be the southwest corner, northeast corner of the rectangle. Typically, you will be getting the sw_point and ne_point from a map that is displayed on a web page.
161
-
162
- If you need to calculate the bounding box from a point and radius, you can do that:
163
-
164
- bounds=Bounds.from_point_and_radius(home,5)
165
- Store.find :all, :bounds=>bounds
166
-
167
- ## USING INCLUDES
168
-
169
- You can use includes along with your distance finders:
170
-
171
- stores=Store.find :all, :origin=>home, :include=>[:reviews,:cities] :within=>5, :order=>'distance'
172
-
173
- *However*, ActiveRecord drops the calculated distance column when you use include. So, if you need to
174
- use the distance column, you'll have to re-calculate it post-query in Ruby:
175
-
176
- stores.sort_by_distance_from(home)
177
-
178
- In this case, you may want to just use the bounding box
179
- condition alone in your SQL (there's no use calculating the distance twice):
180
-
181
- bounds=Bounds.from_point_and_radius(home,5)
182
- stores=Store.find :all, :include=>[:reviews,:cities] :bounds=>bounds
183
- stores.sort_by_distance_from(home)
184
-
185
- ## USING :through
186
-
187
- You can also specify a model as mappable "through" another associated model.
188
- In other words, that associated model is the actual mappable model with
189
- "lat" and "lng" attributes, but this "through" model can still utilize
190
- all of the above find methods to search for records.
191
-
192
- class Location < ActiveRecord::Base
193
- belongs_to :locatable, :polymorphic => true
194
- acts_as_mappable
195
- end
196
-
197
- class Company < ActiveRecord::Base
198
- has_one :location, :as => :locatable # also works for belongs_to associations
199
- acts_as_mappable :through => :location
200
- end
201
-
202
- Then you can still call:
203
-
204
- Company.find_within(distance, :origin => @somewhere)
205
-
206
- You can also give :through a hash if you location is nested deep. For example, given:
207
-
208
- class House
209
- acts_as_mappable
210
- end
211
-
212
- class Family
213
- belongs_to :house
214
- end
215
-
216
- class Person
217
- belongs_to :family
218
- acts_as_mappable :through => { :family => :house }
219
- end
220
-
221
- Remember that the notes above about USING INCLUDES apply to the results from
222
- this find, since an include is automatically used.
223
-
224
- ## IP GEOCODING
225
-
226
- You can obtain the location for an IP at any time using the geocoder
227
- as in the following example:
228
-
229
- location = IpGeocoder.geocode('12.215.42.19')
230
-
231
- where Location is a GeoLoc instance containing the latitude,
232
- longitude, city, state, and country code. Also, the success
233
- value is true.
234
-
235
- If the IP cannot be geocoded, a GeoLoc instance is returned with a
236
- success value of false.
237
-
238
- It should be noted that the IP address needs to be visible to the
239
- Rails application. In other words, you need to ensure that the
240
- requesting IP address is forwarded by any front-end servers that
241
- are out in front of the Rails app. Otherwise, the IP will always
242
- be that of the front-end server.
243
-
244
- The Multi-Geocoder will also geocode IP addresses and provide
245
- failover among multiple IP geocoders. Just pass in an IP address for the
246
- parameter instead of a street address. Eg:
247
-
248
- location = Geocoders::MultiGeocoder.geocode('12.215.42.19')
249
-
250
- The MultiGeocoder class requires 2 configuration setting for the provider order.
251
- Ordering is done through `Geokit::Geocoders::provider_order` and
252
- `Geokit::Geocoders::ip_provider_order`, found in
253
- `config/initializers/geokit_config.rb`. If you don't already have a
254
- `geokit_config.rb` file, the plugin creates one when it is first installed.
255
-
256
-
257
- ## IP GEOCODING HELPER
258
-
259
- A class method called geocode_ip_address has been mixed into the
260
- ActionController::Base. This enables before_filter style lookup of
261
- the IP address. Since it is a filter, it can accept any of the
262
- available filter options.
263
-
264
- Usage is as below:
265
-
266
- class LocationAwareController < ActionController::Base
267
- geocode_ip_address
268
- end
269
-
270
- A first-time lookup will result in the GeoLoc class being stored
271
- in the session as `:geo_location` as well as in a cookie called
272
- `:geo_session`. Subsequent lookups will use the session value if it
273
- exists or the cookie value if it doesn't exist. The last resort is
274
- to make a call to the web service. Clients are free to manage the
275
- cookie as they wish.
276
-
277
- The intent of this feature is to be able to provide a good guess as
278
- to a new visitor's location.
279
-
280
- ## INTEGRATED FIND AND GEOCODING
281
-
282
- Geocoding has been integrated with the finders enabling you to pass
283
- a physical address or an IP address. This would look the following:
284
-
285
- Location.find_farthest(:origin => '217.15.10.9')
286
- Location.find_farthest(:origin => 'Irving, TX')
287
-
288
- where the IP or physical address would be geocoded to a location and
289
- then the resulting latitude and longitude coordinates would be used
290
- in the find. This is not expected to be common usage, but it can be
291
- done nevertheless.
292
-
293
- ## ADDRESS GEOCODING
294
-
295
- Geocoding is provided by the Geokit gem, which is required for this plugin.
296
- See the top of this file for instructions on installing the Geokit gem.
297
-
298
- Geokit can geocode addresses using multiple geocodeing web services.
299
- Geokit supports services like Google, Yahoo, and Geocoder.us, and more --
300
- see the Geokit gem API for a complete list.
301
-
302
- These geocoder services are made available through the following classes:
303
- GoogleGeocoder, YahooGeocoder, UsGeocoder, CaGeocoder, and GeonamesGeocoder.
304
- Further, an additional geocoder class called MultiGeocoder incorporates an ordered failover
305
- sequence to increase the probability of successful geocoding.
306
-
307
- All classes are called using the following signature:
308
-
309
- include Geokit::Geocoders
310
- location = XxxGeocoder.geocode(address)
311
-
312
- where you replace Xxx Geocoder with the appropriate class. A GeoLoc
313
- instance is the result of the call. This class has a "success"
314
- attribute which will be true if a successful geocoding occurred.
315
- If successful, the lat and lng properties will be populated.
316
-
317
- Geocoders are named with the convention NameGeocoder. This
318
- naming convention enables Geocoder to auto-detect its sub-classes
319
- in order to create methods called `name_geocoder(address)` so that
320
- all geocoders can be called through the base class. This is done
321
- purely for convenience; the individual geocoder classes are expected
322
- to be used independently.
323
-
324
- The MultiGeocoder class requires the configuration of a provider
325
- order which dictates what order to use the various geocoders. Ordering
326
- is done through `Geokit::Geocoders::provider_order`, found in
327
- `config/initializers/geokit_config.rb`.
328
-
329
- If you don't already have a `geokit_config.rb` file, the plugin creates one
330
- when it is first installed.
331
-
332
- Make sure your failover configuration matches the usage characteristics
333
- of your application -- for example, if you routinely get bogus input to
334
- geocode, your code will be much slower if you have to failover among
335
- multiple geocoders before determining that the input was in fact bogus.
336
-
337
- The Geocoder.geocode method returns a GeoLoc object. Basic usage:
338
-
339
- loc=Geocoder.geocode('100 Spear St, San Francisco, CA')
340
- if loc.success
341
- puts loc.lat
342
- puts loc.lng
343
- puts loc.full_address
344
- end
345
-
346
- ## REVERSE GEOCODING
347
-
348
- Currently, only the Google Geocoder supports reverse geocoding.
349
- Pass the lat/lng as a string, array or LatLng instance:
350
-
351
- res=Geokit::Geocoders::GoogleGeocoder.reverse_geocode "37.791821,-122.394679"
352
- => #<Geokit::GeoLoc:0x558ed0 ...
353
- res.full_address
354
- "101-115 Main St, San Francisco, CA 94105, USA"
355
-
356
- The address will usually appear as a range, as it does in the above example.
357
-
358
-
359
- ## INTEGRATED FIND WITH ADDRESS GEOCODING
360
-
361
- Just has you can pass an IP address directly into an ActiveRecord finder
362
- as the origin, you can also pass a physical address as the origin:
363
-
364
- Location.find_closest(:origin => '100 Spear st, San Francisco, CA')
365
-
366
- where the physical address would be geocoded to a location and then the
367
- resulting latitude and longitude coordinates would be used in the
368
- find.
369
-
370
- Note that if the address fails to geocode, the find method will raise an
371
- ActiveRecord::GeocodeError you must be prepared to catch. Alternatively,
372
- You can geocoder the address beforehand, and pass the resulting lat/lng
373
- into the finder if successful.
374
-
375
- ## Auto Geocoding
376
-
377
- If your geocoding needs are simple, you can tell your model to automatically
378
- geocode itself on create:
379
-
380
- class Store < ActiveRecord::Base
381
- acts_as_mappable :auto_geocode=>true
382
- end
383
-
384
- It takes two optional params:
385
-
386
- class Store < ActiveRecord::Base
387
- acts_as_mappable :auto_geocode=>{:field=>:address, :error_message=>'Could not geocode address'}
388
- end
389
-
390
- . . . which is equivilent to:
391
-
392
- class Store << ActiveRecord::Base
393
- acts_as_mappable
394
- before_validation_on_create :geocode_address
395
-
396
- private
397
- def geocode_address
398
- geo=Geokit::Geocoders::MultiGeocoder.geocode (address)
399
- errors.add(:address, "Could not Geocode address") if !geo.success
400
- self.lat, self.lng = geo.lat,geo.lng if geo.success
401
- end
402
- end
403
-
404
- If you need any more complicated geocoding behavior for your model, you should roll your own
405
- `before_validate` callback.
406
-
407
-
408
- ## Distances, headings, endpoints, and midpoints
409
-
410
- distance=home.distance_from(work, :units=>:miles)
411
- heading=home.heading_to(work) # result is in degrees, 0 is north
412
- endpoint=home.endpoint(90,2) # two miles due east
413
- midpoing=home.midpoint_to(work)
414
-
415
- ## Cool stuff you can do with bounds
416
-
417
- bounds=Bounds.new(sw_point,ne_point)
418
- bounds.contains?(home)
419
- puts bounds.center
420
-
421
-
422
- HOW TO . . .
423
- =================================================================================
424
-
425
- A few quick examples to get you started ....
426
-
427
- ## How to install the Geokit Rails plugin
428
- (See the very top of this file)
429
-
430
- ## How to find all stores within a 10-mile radius of a given lat/lng
431
- 1. ensure your stores table has lat and lng columns with numeric or float
432
- datatypes to store your latitude/longitude
433
-
434
- 3. use `acts_as_mappable` on your store model:
435
-
436
- class Store < ActiveRecord::Base
437
- acts_as_mappable
438
- ...
439
- end
440
-
441
- 3. finders now have extra capabilities:
442
-
443
- Store.find(:all, :origin =>[32.951613,-96.958444], :within=>10)
444
-
445
- ## How to geocode an address
446
-
447
- 1. configure your geocoder key(s) in `config/initializers/geokit_config.rb`
448
-
449
- 2. also in `geokit_config.rb`, make sure that `Geokit::Geocoders::provider_order` reflects the
450
- geocoder(s). If you only want to use one geocoder, there should
451
- be only one symbol in the array. For example:
452
-
453
- Geokit::Geocoders::provider_order=[:google]
454
-
455
- 3. Test it out in script/console
456
-
457
- include Geokit::Geocoders
458
- res = MultiGeocoder.geocode('100 Spear St, San Francisco, CA')
459
- puts res.lat
460
- puts res.lng
461
- puts res.full_address
462
- ... etc. The return type is GeoLoc, see the API for
463
- all the methods you can call on it.
464
-
465
- ## How to find all stores within 10 miles of a given address
466
-
467
- 1. as above, ensure your table has the lat/lng columns, and you've
468
- applied `acts_as_mappable` to the Store model.
469
-
470
- 2. configure and test out your geocoder, as above
471
-
472
- 3. pass the address in under the :origin key
473
-
474
- Store.find(:all, :origin=>'100 Spear st, San Francisco, CA',
475
- :within=>10)
476
-
477
- 4. you can also use a zipcode, or anything else that's geocodable:
478
-
479
- Store.find(:all, :origin=>'94117',
480
- :conditions=>'distance<10')
481
-
482
- ## How to sort a query by distance from an origin
483
-
484
- You now have access to a 'distance' column, and you can use it
485
- as you would any other column. For example:
486
- Store.find(:all, :origin=>'94117', :order=>'distance')
487
-
488
- ## How to elements of an array according to distance from a common point
489
-
490
- Usually, you can do your sorting in the database as part of your find call.
491
- If you need to sort things post-query, you can do so:
492
-
493
- stores=Store.find :all
494
- stores.sort_by_distance_from(home)
495
- puts stores.first.distance
496
-
497
- Obviously, each of the items in the array must have a latitude/longitude so
498
- they can be sorted by distance.
499
-
500
- ## Database indexes
501
-
502
- MySQL can't create indexes on a calculated field such as those Geokit uses to
503
- calculate distance based on latitude/longitude values for a record. However,
504
- indexing the lat and lng columns does improve Geokit distance calculation
505
- performance since the lat and lng columns are used in a straight comparison
506
- for distance calculation. Assuming a Page model that is incorporating the
507
- Geokit plugin the migration would be as follows.
508
-
509
- class AddIndexOPageLatAndLng < ActiveRecord::Migration
510
-
511
- def self.up
512
- add_index :pages, [:lat, :lng]
513
- end
514
-
515
- def self.down
516
- remove_index :pages, [:lat, :lng]
517
- end
518
- end
519
-
520
- ## Database Compatability
521
-
522
- * Geokit works with MySQL (tested with version 5.0.41), PostgreSQL (tested with version 8.2.6) and Microsoft SQL Server (tested with 2000).
523
- * Geokit does *not* work with SQLite, as it lacks the necessary geometry functions.
524
- * Geokit is known to *not* work with Postgres versions under 8.1 -- it uses the least() funciton.
525
-
526
-
527
- ## HIGH-LEVEL NOTES ON WHAT'S WHERE
528
-
529
- `acts_as_mappable.rb`, as you'd expect, contains the ActsAsMappable
530
- module which gets mixed into your models to provide the
531
- location-based finder goodness.
532
-
533
- `ip_geocode_lookup.rb` contains the before_filter helper method which
534
- enables auto lookup of the requesting IP address.
535
-
536
- ### The Geokit gem provides the building blocks of distance-based operations:
537
-
538
- The Mappable module, which provides basic
539
- distance calculation methods, i.e., calculating the distance
540
- between two points.
541
-
542
- The LatLng class is a simple container for latitude and longitude, but
543
- it's made more powerful by mixing in the above-mentioned Mappable
544
- module -- therefore, you can calculate easily the distance between two
545
- LatLng ojbects with `distance = first.distance_to(other)`
546
-
547
- GeoLoc represents an address or location which
548
- has been geocoded. You can get the city, zipcode, street address, etc.
549
- from a GeoLoc object. GeoLoc extends LatLng, so you also get lat/lng
550
- AND the Mappable modeule goodness for free.
551
-
552
- ## GOOGLE GROUP
553
-
554
- Follow the Google Group for updates and discussion on Geokit: http://groups.google.com/group/geokit
555
-
556
- ## IMPORTANT POST-INSTALLATION NOTES:
557
-
558
- *1. The configuration file*: Geokit for Rails uses a configuration file in config/initializers.
559
- You *must* add your own keys for the various geocoding services if you want to use geocoding.
560
- If you need to refer to the original template again, see the `assets/api_keys_template` file.
561
-
562
- *2. The gem dependency*: Geokit for Rails depends on the Geokit gem. Tell Rails about this
563
- dependency in `config/environment.rb`, within the initializer block:
564
- config.gem "geokit"
565
-
566
- *If you're having trouble with dependencies ....*
567
-
568
- Try installing the gem manually (sudo gem install geokit), then adding a `require 'geokit'` to the top of
569
- `vendor/plugins/geokit-rails/init.rb` and/or `config/geokit_config.rb`.