geokit-rails3 0.0.5 → 0.1.0
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.
- data/lib/geokit-rails3/acts_as_mappable.rb +78 -59
- data/lib/geokit-rails3/version.rb +1 -1
- metadata +4 -4
@@ -48,38 +48,6 @@ module Geokit
|
|
48
48
|
# set the actual callback here
|
49
49
|
before_validation :auto_geocode_address, :on => :create
|
50
50
|
end
|
51
|
-
|
52
|
-
scope :select_with_distance, lambda { |origin, units, formula|
|
53
|
-
distance_formula = distance_sql(origin, units, formula)
|
54
|
-
|
55
|
-
select('*').
|
56
|
-
select("#{distance_formula} AS #{distance_column_name}")
|
57
|
-
}
|
58
|
-
|
59
|
-
scope :within, lambda { |options|
|
60
|
-
origin = extract_origin_from_options(options)
|
61
|
-
units = extract_units_from_options(options)
|
62
|
-
formula = extract_formula_from_options(options)
|
63
|
-
|
64
|
-
distance_formula = distance_sql(origin, units, formula)
|
65
|
-
|
66
|
-
within = options.delete(:within)
|
67
|
-
|
68
|
-
select_with_distance(origin, units, formula).
|
69
|
-
where("#{distance_formula} < #{within}")
|
70
|
-
}
|
71
|
-
|
72
|
-
scope :closest, lambda { |options|
|
73
|
-
origin = extract_origin_from_options(options)
|
74
|
-
units = extract_units_from_options(options)
|
75
|
-
formula = extract_formula_from_options(options)
|
76
|
-
|
77
|
-
distance_formula = distance_sql(origin, units, formula)
|
78
|
-
|
79
|
-
select_with_distance(origin, units, formula).
|
80
|
-
order("#{distance_formula} ASC").
|
81
|
-
limit(1)
|
82
|
-
}
|
83
51
|
end
|
84
52
|
end
|
85
53
|
end
|
@@ -106,6 +74,68 @@ module Geokit
|
|
106
74
|
end
|
107
75
|
end
|
108
76
|
|
77
|
+
def within(distance, options = {})
|
78
|
+
options[:within] = distance
|
79
|
+
geo_scope(options)
|
80
|
+
end
|
81
|
+
alias inside within
|
82
|
+
|
83
|
+
def beyond(distance, options = {})
|
84
|
+
options[:beyond] = distance
|
85
|
+
geo_scope(options)
|
86
|
+
end
|
87
|
+
alias outside beyond
|
88
|
+
|
89
|
+
def in_range(range, options = {})
|
90
|
+
options[:range] = range
|
91
|
+
geo_scope(options)
|
92
|
+
end
|
93
|
+
|
94
|
+
def in_bounds(bounds, options = {})
|
95
|
+
options[:bounds] = bounds
|
96
|
+
geo_scope(options)
|
97
|
+
end
|
98
|
+
|
99
|
+
def closest(options = {})
|
100
|
+
geo_scope(options).order("#{distance_column_name} asc").limit(1)
|
101
|
+
end
|
102
|
+
alias nearest closest
|
103
|
+
|
104
|
+
def farthest(options = {})
|
105
|
+
geo_scope(options).order("#{distance_column_name} desc").limit(1)
|
106
|
+
end
|
107
|
+
|
108
|
+
def geo_scope(options = {})
|
109
|
+
arel = self.is_a?(ActiveRecord::Relation) ? self : self.scoped
|
110
|
+
|
111
|
+
origin = extract_origin_from_options(options)
|
112
|
+
units = extract_units_from_options(options)
|
113
|
+
formula = extract_formula_from_options(options)
|
114
|
+
bounds = extract_bounds_from_options(options)
|
115
|
+
|
116
|
+
if origin || bounds
|
117
|
+
bounds = formulate_bounds_from_distance(options, origin, units) unless bounds
|
118
|
+
|
119
|
+
if origin
|
120
|
+
distance_formula = distance_sql(origin, units, formula)
|
121
|
+
arel = arel.select('*') if arel.select_values.blank?
|
122
|
+
arel = arel.select("#{distance_formula} AS #{distance_column_name}")
|
123
|
+
end
|
124
|
+
|
125
|
+
if bounds
|
126
|
+
bound_conditions = bound_conditions(bounds)
|
127
|
+
arel = arel.where(bound_conditions) if bound_conditions
|
128
|
+
end
|
129
|
+
|
130
|
+
distance_conditions = distance_conditions(options)
|
131
|
+
arel = arel.where(distance_conditions) if distance_conditions
|
132
|
+
|
133
|
+
arel = substitute_distance_in_where_values(arel, origin, units, formula)
|
134
|
+
end
|
135
|
+
|
136
|
+
arel
|
137
|
+
end
|
138
|
+
|
109
139
|
# Returns the distance calculation to be used as a display column or a condition. This
|
110
140
|
# is provide for anyone wanting access to the raw SQL.
|
111
141
|
def distance_sql(origin, units=default_units, formula=default_formula)
|
@@ -131,30 +161,21 @@ module Geokit
|
|
131
161
|
nil
|
132
162
|
end
|
133
163
|
end
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
def apply_distance_scope(options)
|
138
|
-
distance_condition = if options.has_key?(:within)
|
164
|
+
|
165
|
+
def distance_conditions(options)
|
166
|
+
if options.has_key?(:within)
|
139
167
|
"#{distance_column_name} <= #{options[:within]}"
|
140
168
|
elsif options.has_key?(:beyond)
|
141
169
|
"#{distance_column_name} > #{options[:beyond]}"
|
142
170
|
elsif options.has_key?(:range)
|
143
171
|
"#{distance_column_name} >= #{options[:range].first} AND #{distance_column_name} <#{'=' unless options[:range].exclude_end?} #{options[:range].last}"
|
144
172
|
end
|
145
|
-
|
146
|
-
if distance_condition
|
147
|
-
[:within, :beyond, :range].each { |option| options.delete(option) }
|
148
|
-
options[:conditions] = merge_conditions(options[:conditions], distance_condition)
|
149
|
-
end
|
150
173
|
end
|
151
|
-
|
152
|
-
|
153
|
-
def apply_bounds_conditions(options,bounds)
|
174
|
+
|
175
|
+
def bound_conditions(bounds)
|
154
176
|
sw,ne = bounds.sw, bounds.ne
|
155
177
|
lng_sql = bounds.crosses_meridian? ? "(#{qualified_lng_column_name}<#{ne.lng} OR #{qualified_lng_column_name}>#{sw.lng})" : "#{qualified_lng_column_name}>#{sw.lng} AND #{qualified_lng_column_name}<#{ne.lng}"
|
156
|
-
|
157
|
-
options[:conditions] = merge_conditions(options[:conditions], bounds_sql)
|
178
|
+
"#{qualified_lat_column_name}>#{sw.lat} AND #{qualified_lat_column_name}<#{ne.lat} AND #{lng_sql}"
|
158
179
|
end
|
159
180
|
|
160
181
|
# Extracts the origin instance out of the options if it exists and returns
|
@@ -207,23 +228,21 @@ module Geokit
|
|
207
228
|
res
|
208
229
|
end
|
209
230
|
|
210
|
-
# Augments the select with the distance SQL.
|
211
|
-
def add_distance_to_select(options, origin, units=default_units, formula=default_formula)
|
212
|
-
if origin
|
213
|
-
distance_selector = distance_sql(origin, units, formula) + " AS #{distance_column_name}"
|
214
|
-
selector = options.has_key?(:select) && options[:select] ? options[:select] : "*"
|
215
|
-
options[:select] = "#{selector}, #{distance_selector}"
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
231
|
# Looks for the distance column and replaces it with the distance sql. If an origin was not
|
220
232
|
# passed in and the distance column exists, we leave it to be flagged as bad SQL by the database.
|
221
233
|
# Conditions are either a string or an array. In the case of an array, the first entry contains
|
222
234
|
# the condition.
|
223
|
-
def
|
224
|
-
condition = options[:conditions].is_a?(String) ? options[:conditions] : options[:conditions].first
|
235
|
+
def substitute_distance_in_where_values(arel, origin, units=default_units, formula=default_formula)
|
225
236
|
pattern = Regexp.new("\\b#{distance_column_name}\\b")
|
226
|
-
|
237
|
+
value = distance_sql(origin, units, formula)
|
238
|
+
arel.where_values.map! do |where_value|
|
239
|
+
if where_value.is_a?(String)
|
240
|
+
where_value.gsub(pattern, value)
|
241
|
+
else
|
242
|
+
where_value
|
243
|
+
end
|
244
|
+
end
|
245
|
+
arel
|
227
246
|
end
|
228
247
|
|
229
248
|
# Returns the distance SQL using the spherical world formula (Haversine). The SQL is tuned
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geokit-rails3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.5
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andre Lewis
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2010-10-
|
20
|
+
date: 2010-10-14 00:00:00 +02:00
|
21
21
|
default_executable:
|
22
22
|
dependencies:
|
23
23
|
- !ruby/object:Gem::Dependency
|