geokit-rails 2.0.1 → 2.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of geokit-rails might be problematic. Click here for more details.
- checksums.yaml +6 -14
- data/.gitignore +37 -0
- data/.travis.yml +29 -0
- data/CHANGELOG.md +96 -0
- data/CONFIG.markdown +67 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +726 -0
- data/Rakefile +17 -0
- data/gemfiles/rails3.gemfile +7 -0
- data/gemfiles/rails4.gemfile +8 -0
- data/gemfiles/rails5.gemfile +8 -0
- data/geokit-rails.gemspec +33 -0
- data/lib/generators/geokit_rails/install_generator.rb +13 -0
- data/lib/generators/templates/geokit_config.rb +100 -0
- data/lib/geokit-rails.rb +0 -1
- data/lib/geokit-rails/acts_as_mappable.rb +87 -37
- data/lib/geokit-rails/adapters/oracleenhanced.rb +32 -0
- data/lib/geokit-rails/adapters/sqlite.rb +2 -2
- data/lib/geokit-rails/adapters/sqlserver.rb +19 -17
- data/lib/geokit-rails/geocoder_control.rb +7 -6
- data/lib/geokit-rails/ip_geocode_lookup.rb +17 -13
- data/lib/geokit-rails/railtie.rb +0 -1
- data/lib/geokit-rails/version.rb +1 -1
- data/test/acts_as_mappable_test.rb +30 -6
- data/test/boot.rb +3 -3
- data/test/fixtures/companies.yml +3 -1
- data/test/fixtures/custom_locations.yml +8 -1
- data/test/fixtures/locations.yml +8 -1
- data/test/schema.rb +1 -0
- data/test/test_helper.rb +17 -5
- metadata +120 -92
- data/lib/geokit-rails/defaults.rb +0 -21
- data/test/mysql-debug.log +0 -1057
- data/test/mysql2-debug.log +0 -2758
- data/test/mysql2spatial-debug.log +0 -3619
- data/test/postgres-debug.log +0 -1
- data/test/postgresql-debug.log +0 -1
- data/test/sqlite-debug.log +0 -67286
- data/test/test.sqlite3 +0 -0
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rdoc/task'
|
5
|
+
Rake::RDocTask.new do |rdoc|
|
6
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
7
|
+
|
8
|
+
rdoc.rdoc_dir = 'rdoc'
|
9
|
+
rdoc.title = "geokit-rails #{version}"
|
10
|
+
rdoc.rdoc_files.include('README*')
|
11
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
12
|
+
end
|
13
|
+
|
14
|
+
load 'test/tasks.rake'
|
15
|
+
|
16
|
+
desc 'Default: run unit tests.'
|
17
|
+
task :default => :test
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/geokit-rails/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = "geokit-rails"
|
6
|
+
spec.version = GeokitRails::VERSION
|
7
|
+
spec.authors = ["Michael Noack", "Andre Lewis", "Bill Eisenhauer", "Jeremy Lecour"]
|
8
|
+
spec.email = ["michael+geokit@noack.com.au", "andre@earthcode.com", "bill_eisenhauer@yahoo.com", "jeremy.lecour@gmail.com"]
|
9
|
+
spec.summary = "Integrate Geokit with Rails"
|
10
|
+
spec.description = "Official Geokit plugin for Rails/ActiveRecord. Provides location-based goodness for your Rails app. Requires the Geokit gem."
|
11
|
+
spec.summary = "Geokit helpers for rails apps."
|
12
|
+
spec.homepage = "http://github.com/geokit/geokit-rails"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency 'rails', '>= 3.0'
|
21
|
+
spec.add_dependency 'geokit', '~> 1.5'
|
22
|
+
spec.add_development_dependency "bundler", "> 1.0"
|
23
|
+
spec.add_development_dependency "simplecov", "~> 0.16.1"
|
24
|
+
spec.add_development_dependency "simplecov-rcov"
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'test-unit'
|
27
|
+
spec.add_development_dependency "mocha", "~> 0.9"
|
28
|
+
spec.add_development_dependency 'coveralls'
|
29
|
+
spec.add_development_dependency "mysql2", "~> 0.2"
|
30
|
+
spec.add_development_dependency "activerecord-mysql2spatial-adapter"
|
31
|
+
spec.add_development_dependency "pg", "~> 0.10"
|
32
|
+
spec.add_development_dependency "sqlite3"
|
33
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module GeokitRails
|
2
|
+
module Generators
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path("../../templates", __FILE__)
|
5
|
+
|
6
|
+
desc "Creates a sample Geokit initializer."
|
7
|
+
|
8
|
+
def copy_initializer
|
9
|
+
copy_file "geokit_config.rb", "config/initializers/geokit_config.rb"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# These defaults are used in Geokit::Mappable.distance_to and acts_as_mappable
|
2
|
+
Geokit::default_units = :miles # others :kms, :nms, :meters
|
3
|
+
Geokit::default_formula = :sphere
|
4
|
+
|
5
|
+
# This is the timeout value in seconds to be used for calls to the geocoder web
|
6
|
+
# services. For no timeout at all, comment out the setting. The timeout unit
|
7
|
+
# is in seconds.
|
8
|
+
Geokit::Geocoders::request_timeout = 3
|
9
|
+
|
10
|
+
# This setting can be used if web service calls must be routed through a proxy.
|
11
|
+
# These setting can be nil if not needed, otherwise, a valid URI must be
|
12
|
+
# filled in at a minimum. If the proxy requires authentication, the username
|
13
|
+
# and password can be provided as well.
|
14
|
+
# Geokit::Geocoders::proxy = 'https://user:password@host:port'
|
15
|
+
|
16
|
+
# This is your yahoo application key for the Yahoo Geocoder.
|
17
|
+
# See http://developer.yahoo.com/faq/index.html#appid
|
18
|
+
# and http://developer.yahoo.com/maps/rest/V1/geocode.html
|
19
|
+
# Geokit::Geocoders::YahooGeocoder.key = 'REPLACE_WITH_YOUR_YAHOO_KEY'
|
20
|
+
# Geokit::Geocoders::YahooGeocoder.secret = 'REPLACE_WITH_YOUR_YAHOO_SECRET'
|
21
|
+
|
22
|
+
# This is your Google Maps geocoder keys (all optional).
|
23
|
+
# See http://www.google.com/apis/maps/signup.html
|
24
|
+
# and http://www.google.com/apis/maps/documentation/#Geocoding_Examples
|
25
|
+
# Geokit::Geocoders::GoogleGeocoder.client_id = ''
|
26
|
+
# Geokit::Geocoders::GoogleGeocoder.cryptographic_key = ''
|
27
|
+
# Geokit::Geocoders::GoogleGeocoder.channel = ''
|
28
|
+
|
29
|
+
# You can also use the free API key instead of signed requests
|
30
|
+
# See https://developers.google.com/maps/documentation/geocoding/#api_key
|
31
|
+
# Geokit::Geocoders::GoogleGeocoder.api_key = ''
|
32
|
+
|
33
|
+
# You can also set multiple API KEYS for different domains that may be directed
|
34
|
+
# to this same application.
|
35
|
+
# The domain from which the current user is being directed will automatically
|
36
|
+
# be updated for Geokit via
|
37
|
+
# the GeocoderControl class, which gets it's begin filter mixed
|
38
|
+
# into the ActionController.
|
39
|
+
# You define these keys with a Hash as follows:
|
40
|
+
# Geokit::Geocoders::google = {
|
41
|
+
# 'rubyonrails.org' => 'RUBY_ON_RAILS_API_KEY',
|
42
|
+
# ' ruby-docs.org' => 'RUBY_DOCS_API_KEY' }
|
43
|
+
|
44
|
+
# This is your username and password for geocoder.us.
|
45
|
+
# To use the free service, the value can be set to nil or false. For
|
46
|
+
# usage tied to an account, the value should be set to username:password.
|
47
|
+
# See http://geocoder.us
|
48
|
+
# and http://geocoder.us/user/signup
|
49
|
+
# Geokit::Geocoders::UsGeocoder.key = 'username:password'
|
50
|
+
|
51
|
+
# This is your authorization key for geocoder.ca.
|
52
|
+
# To use the free service, the value can be set to nil or false. For
|
53
|
+
# usage tied to an account, set the value to the key obtained from
|
54
|
+
# Geocoder.ca.
|
55
|
+
# See http://geocoder.ca
|
56
|
+
# and http://geocoder.ca/?register=1
|
57
|
+
# Geokit::Geocoders::CaGeocoder.key = 'KEY'
|
58
|
+
|
59
|
+
# This is your username key for geonames.
|
60
|
+
# To use this service either free or premium, you must register a key.
|
61
|
+
# See http://www.geonames.org
|
62
|
+
# Geokit::Geocoders::GeonamesGeocoder.key = 'KEY'
|
63
|
+
|
64
|
+
# Most other geocoders need either no setup or a key
|
65
|
+
# Geokit::Geocoders::BingGeocoder.key = ''
|
66
|
+
# Geokit::Geocoders::MapQuestGeocoder.key = ''
|
67
|
+
# Geokit::Geocoders::YandexGeocoder.key = ''
|
68
|
+
# Geokit::Geocoders::MapboxGeocoder.key = 'ACCESS_TOKEN'
|
69
|
+
# Geokit::Geocoders::OpencageGeocoder.key = 'some_api_key'
|
70
|
+
|
71
|
+
# Geonames has a free service and a premium service, each using a different URL
|
72
|
+
# GeonamesGeocoder.premium = true will use http://ws.geonames.net (premium)
|
73
|
+
# GeonamesGeocoder.premium = false will use http://api.geonames.org (free)
|
74
|
+
# Geokit::Geocoders::GeonamesGeocoder.premium = false
|
75
|
+
|
76
|
+
# require "external_geocoder.rb"
|
77
|
+
# Please see the section "writing your own geocoders" for more information.
|
78
|
+
# Geokit::Geocoders::external_key = 'REPLACE_WITH_YOUR_API_KEY'
|
79
|
+
|
80
|
+
# This is the order in which the geocoders are called in a failover scenario
|
81
|
+
# If you only want to use a single geocoder, put a single symbol in the array.
|
82
|
+
# Valid symbols are :google, :yahoo, :us, and :ca.
|
83
|
+
# Be aware that there are Terms of Use restrictions on how you can use the
|
84
|
+
# various geocoders. Make sure you read up on relevant Terms of Use for each
|
85
|
+
# geocoder you are going to use.
|
86
|
+
# Geokit::Geocoders::provider_order = [:google,:us]
|
87
|
+
|
88
|
+
# The IP provider order. Valid symbols are :ip,:geo_plugin.
|
89
|
+
# As before, make sure you read up on relevant Terms of Use for each.
|
90
|
+
# Geokit::Geocoders::ip_provider_order = [:external,:geo_plugin,:ip]
|
91
|
+
|
92
|
+
# Disable HTTPS globally. This option can also be set on individual
|
93
|
+
# geocoder classes.
|
94
|
+
# Geokit::Geocoders::secure = false
|
95
|
+
|
96
|
+
# Control verification of the server certificate for geocoders using HTTPS
|
97
|
+
# Geokit::Geocoders::ssl_verify_mode = OpenSSL::SSL::VERIFY_(PEER/NONE)
|
98
|
+
# Setting this to VERIFY_NONE may be needed on systems that don't have
|
99
|
+
# a complete or up to date root certificate store. Only applies to
|
100
|
+
# the Net::HTTP adapter.
|
data/lib/geokit-rails.rb
CHANGED
@@ -11,6 +11,8 @@ module Geokit
|
|
11
11
|
extend ActiveSupport::Concern
|
12
12
|
|
13
13
|
module ClassMethods # :nodoc:
|
14
|
+
OPTION_SYMBOLS = [ :distance_column_name, :default_units, :default_formula, :lat_column_name, :lng_column_name, :qualified_lat_column_name, :qualified_lng_column_name, :skip_loading ]
|
15
|
+
|
14
16
|
def acts_as_mappable(options = {})
|
15
17
|
metaclass = (class << self; self; end)
|
16
18
|
|
@@ -21,20 +23,21 @@ module Geokit
|
|
21
23
|
|
22
24
|
if reflection = Geokit::ActsAsMappable.end_of_reflection_chain(self.through, self)
|
23
25
|
metaclass.instance_eval do
|
24
|
-
|
26
|
+
OPTION_SYMBOLS.each do |method_name|
|
25
27
|
define_method method_name do
|
26
28
|
reflection.klass.send(method_name)
|
27
29
|
end
|
28
30
|
end
|
29
31
|
end
|
30
32
|
else
|
31
|
-
cattr_accessor
|
33
|
+
cattr_accessor *OPTION_SYMBOLS
|
32
34
|
|
33
35
|
self.distance_column_name = options[:distance_column_name] || 'distance'
|
34
36
|
self.default_units = options[:default_units] || Geokit::default_units
|
35
37
|
self.default_formula = options[:default_formula] || Geokit::default_formula
|
36
38
|
self.lat_column_name = options[:lat_column_name] || 'lat'
|
37
39
|
self.lng_column_name = options[:lng_column_name] || 'lng'
|
40
|
+
self.skip_loading = options[:skip_loading]
|
38
41
|
self.qualified_lat_column_name = "#{table_name}.#{lat_column_name}"
|
39
42
|
self.qualified_lng_column_name = "#{table_name}.#{lng_column_name}"
|
40
43
|
|
@@ -91,11 +94,21 @@ module Geokit
|
|
91
94
|
module ClassMethods
|
92
95
|
|
93
96
|
# A proxy to an instance of a finder adapter, inferred from the connection's adapter.
|
94
|
-
def
|
95
|
-
@
|
96
|
-
|
97
|
+
def geokit_finder_adapter
|
98
|
+
@geokit_finder_adapter ||= begin
|
99
|
+
unless Adapters.const_defined?(connection.adapter_name.camelcase)
|
100
|
+
filename = connection.adapter_name.downcase
|
101
|
+
require File.join("geokit-rails", "adapters", filename)
|
102
|
+
end
|
97
103
|
klass = Adapters.const_get(connection.adapter_name.camelcase)
|
98
|
-
klass.
|
104
|
+
if klass.class == Module
|
105
|
+
# For some reason Mysql2 adapter was defined in Adapters.constants but was Module instead of a Class
|
106
|
+
filename = connection.adapter_name.downcase
|
107
|
+
require File.join("geokit-rails", "adapters", filename)
|
108
|
+
# Re-init the klass after require
|
109
|
+
klass = Adapters.const_get(connection.adapter_name.camelcase)
|
110
|
+
end
|
111
|
+
klass.load(self) unless klass.loaded || skip_loading
|
99
112
|
klass.new(self)
|
100
113
|
rescue LoadError
|
101
114
|
raise UnsupportedAdapter, "`#{connection.adapter_name.downcase}` is not a supported adapter."
|
@@ -104,8 +117,13 @@ module Geokit
|
|
104
117
|
|
105
118
|
def within(distance, options = {})
|
106
119
|
options[:within] = distance
|
107
|
-
#
|
108
|
-
|
120
|
+
# Add bounding box to speed up SQL request.
|
121
|
+
bounds = formulate_bounds_from_distance(
|
122
|
+
options,
|
123
|
+
normalize_point_to_lat_lng(options[:origin]),
|
124
|
+
options[:units] || default_units)
|
125
|
+
with_latlng.where(bound_conditions(bounds)).
|
126
|
+
where(distance_conditions(options))
|
109
127
|
end
|
110
128
|
alias inside within
|
111
129
|
|
@@ -123,30 +141,35 @@ module Geokit
|
|
123
141
|
end
|
124
142
|
|
125
143
|
def in_bounds(bounds, options = {})
|
144
|
+
inclusive = options.delete(:inclusive) || false
|
126
145
|
options[:bounds] = bounds
|
127
146
|
#geo_scope(options)
|
128
147
|
#where(distance_conditions(options))
|
129
148
|
bounds = extract_bounds_from_options(options)
|
130
|
-
where(bound_conditions(bounds))
|
149
|
+
where(bound_conditions(bounds, inclusive))
|
131
150
|
end
|
132
151
|
|
133
152
|
def by_distance(options = {})
|
134
153
|
origin = extract_origin_from_options(options)
|
135
154
|
units = extract_units_from_options(options)
|
136
155
|
formula = extract_formula_from_options(options)
|
137
|
-
bounds = extract_bounds_from_options(options)
|
138
156
|
distance_column_name = distance_sql(origin, units, formula)
|
139
|
-
|
140
|
-
|
157
|
+
with_latlng.order(
|
158
|
+
Arel.sql(distance_column_name).send(options[:reverse] ? 'desc' : 'asc')
|
159
|
+
)
|
160
|
+
end
|
161
|
+
|
162
|
+
def with_latlng
|
163
|
+
where("#{qualified_lat_column_name} IS NOT NULL AND #{qualified_lng_column_name} IS NOT NULL")
|
141
164
|
end
|
142
165
|
|
143
166
|
def closest(options = {})
|
144
|
-
by_distance(options).
|
167
|
+
by_distance(options).limit(1)
|
145
168
|
end
|
146
169
|
alias nearest closest
|
147
170
|
|
148
171
|
def farthest(options = {})
|
149
|
-
by_distance(options).
|
172
|
+
by_distance({:reverse => true}.merge(options)).limit(1)
|
150
173
|
end
|
151
174
|
|
152
175
|
#def geo_scope(options = {})
|
@@ -162,9 +185,9 @@ module Geokit
|
|
162
185
|
|
163
186
|
# if origin
|
164
187
|
# arel.distance_formula = distance_sql(origin, units, formula)
|
165
|
-
#
|
188
|
+
#
|
166
189
|
# if arel.select_values.blank?
|
167
|
-
# star_select = Arel::SqlLiteral.new(arel.quoted_table_name + '.*')
|
190
|
+
# star_select = Arel::Nodes::SqlLiteral.new(arel.quoted_table_name + '.*')
|
168
191
|
# arel = arel.select(star_select)
|
169
192
|
# end
|
170
193
|
# end
|
@@ -211,10 +234,10 @@ module Geokit
|
|
211
234
|
# If it's a :within query, add a bounding box to improve performance.
|
212
235
|
# This only gets called if a :bounds argument is not otherwise supplied.
|
213
236
|
def formulate_bounds_from_distance(options, origin, units)
|
214
|
-
distance = options[:within] if options.has_key?(:within)
|
237
|
+
distance = options[:within] if options.has_key?(:within) && options[:within].is_a?(Numeric)
|
215
238
|
distance = options[:range].last-(options[:range].exclude_end?? 1 : 0) if options.has_key?(:range)
|
216
239
|
if distance
|
217
|
-
|
240
|
+
Geokit::Bounds.from_point_and_radius(origin,distance,:units=>units)
|
218
241
|
else
|
219
242
|
nil
|
220
243
|
end
|
@@ -224,25 +247,41 @@ module Geokit
|
|
224
247
|
origin = extract_origin_from_options(options)
|
225
248
|
units = extract_units_from_options(options)
|
226
249
|
formula = extract_formula_from_options(options)
|
227
|
-
bounds = extract_bounds_from_options(options)
|
228
250
|
distance_column_name = distance_sql(origin, units, formula)
|
229
251
|
|
230
|
-
|
231
|
-
|
252
|
+
if options.has_key?(:within)
|
253
|
+
Arel.sql(distance_column_name).lteq(options[:within])
|
232
254
|
elsif options.has_key?(:beyond)
|
233
|
-
|
255
|
+
Arel.sql(distance_column_name).gt(options[:beyond])
|
234
256
|
elsif options.has_key?(:range)
|
235
|
-
|
257
|
+
min_condition = Arel.sql(distance_column_name).gteq(options[:range].begin)
|
258
|
+
max_condition = if options[:range].exclude_end?
|
259
|
+
Arel.sql(distance_column_name).lt(options[:range].end)
|
260
|
+
else
|
261
|
+
Arel.sql(distance_column_name).lteq(options[:range].end)
|
262
|
+
end
|
263
|
+
min_condition.and(max_condition)
|
236
264
|
end
|
237
|
-
Arel::SqlLiteral.new("(#{res})") if res.present?
|
238
265
|
end
|
239
266
|
|
240
|
-
def bound_conditions(bounds)
|
267
|
+
def bound_conditions(bounds, inclusive = false)
|
268
|
+
return nil unless bounds
|
269
|
+
if inclusive
|
270
|
+
lt_operator = :lteq
|
271
|
+
gt_operator = :gteq
|
272
|
+
else
|
273
|
+
lt_operator = :lt
|
274
|
+
gt_operator = :gt
|
275
|
+
end
|
241
276
|
sw,ne = bounds.sw, bounds.ne
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
277
|
+
lat, lng = Arel.sql(qualified_lat_column_name), Arel.sql(qualified_lng_column_name)
|
278
|
+
lat.send(gt_operator, sw.lat).and(lat.send(lt_operator, ne.lat)).and(
|
279
|
+
if bounds.crosses_meridian?
|
280
|
+
lng.send(lt_operator, ne.lng).or(lng.send(gt_operator, sw.lng))
|
281
|
+
else
|
282
|
+
lng.send(gt_operator, sw.lng).and(lng.send(lt_operator, ne.lng))
|
283
|
+
end
|
284
|
+
)
|
246
285
|
end
|
247
286
|
|
248
287
|
# Extracts the origin instance out of the options if it exists and returns
|
@@ -315,20 +354,31 @@ module Geokit
|
|
315
354
|
# Returns the distance SQL using the spherical world formula (Haversine). The SQL is tuned
|
316
355
|
# to the database in use.
|
317
356
|
def sphere_distance_sql(origin, units)
|
318
|
-
|
319
|
-
|
357
|
+
# "origin" can be a Geokit::LatLng (with :lat and :lng methods), e.g.
|
358
|
+
# when using geo_scope or it can be an ActsAsMappable with customized
|
359
|
+
# latitude and longitude methods, e.g. when using distance_sql.
|
360
|
+
lat = deg2rad(get_lat(origin))
|
361
|
+
lng = deg2rad(get_lng(origin))
|
320
362
|
multiplier = units_sphere_multiplier(units)
|
321
|
-
|
322
|
-
adapter.sphere_distance_sql(lat, lng, multiplier) if adapter
|
363
|
+
geokit_finder_adapter.sphere_distance_sql(lat, lng, multiplier) if geokit_finder_adapter
|
323
364
|
end
|
324
365
|
|
325
366
|
# Returns the distance SQL using the flat-world formula (Phythagorean Theory). The SQL is tuned
|
326
367
|
# to the database in use.
|
327
368
|
def flat_distance_sql(origin, units)
|
328
369
|
lat_degree_units = units_per_latitude_degree(units)
|
329
|
-
lng_degree_units = units_per_longitude_degree(origin
|
370
|
+
lng_degree_units = units_per_longitude_degree(get_lat(origin), units)
|
371
|
+
geokit_finder_adapter.flat_distance_sql(origin, lat_degree_units, lng_degree_units)
|
372
|
+
end
|
373
|
+
|
374
|
+
def get_lat(origin)
|
375
|
+
origin.respond_to?(:lat) ? origin.lat \
|
376
|
+
: origin.send(:"#{lat_column_name}")
|
377
|
+
end
|
330
378
|
|
331
|
-
|
379
|
+
def get_lng(origin)
|
380
|
+
origin.respond_to?(:lng) ? origin.lng \
|
381
|
+
: origin.send(:"#{lng_column_name}")
|
332
382
|
end
|
333
383
|
|
334
384
|
end # ClassMethods
|
@@ -339,8 +389,8 @@ module Geokit
|
|
339
389
|
geo=Geokit::Geocoders::MultiGeocoder.geocode(address)
|
340
390
|
|
341
391
|
if geo.success
|
342
|
-
self.send("#{lat_column_name}=", geo.
|
343
|
-
self.send("#{lng_column_name}=", geo.
|
392
|
+
self.send("#{lat_column_name}=", geo.send(:"#{lat_column_name}"))
|
393
|
+
self.send("#{lng_column_name}=", geo.send(:"#{lng_column_name}"))
|
344
394
|
else
|
345
395
|
errors.add(auto_geocode_field, auto_geocode_error_message)
|
346
396
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Geokit
|
2
|
+
module Adapters
|
3
|
+
class OracleEnhanced < Abstract
|
4
|
+
TO_DEGREES = Math::PI / 180
|
5
|
+
def sphere_distance_sql(lat, lng, multiplier)
|
6
|
+
%{
|
7
|
+
(
|
8
|
+
ACOS(
|
9
|
+
COS(#{lat}) * COS(#{lng}) *
|
10
|
+
COS(#{TO_DEGREES} * #{qualified_lat_column_name}) *
|
11
|
+
COS(#{TO_DEGREES} * #{qualified_lng_column_name}) +
|
12
|
+
COS(#{lat}) * SIN(#{lng}) *
|
13
|
+
COS(#{TO_DEGREES} * #{qualified_lat_column_name}) *
|
14
|
+
SIN(#{TO_DEGREES} * #{qualified_lng_column_name}) +
|
15
|
+
SIN(#{lat}) *
|
16
|
+
SIN(#{TO_DEGREES} * #{qualified_lat_column_name})
|
17
|
+
) *
|
18
|
+
#{multiplier})
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def flat_distance_sql(origin, lat_degree_units, lng_degree_units)
|
23
|
+
%{
|
24
|
+
SQRT(
|
25
|
+
POWER(#{lat_degree_units}*(#{origin.lat}-#{qualified_lat_column_name}), 2)
|
26
|
+
POWER(#{lng_degree_units}*(#{origin.lng}-#{qualified_lng_column_name}), 2)
|
27
|
+
)
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|