dm-geokit 0.10.1
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/LICENSE +20 -0
- data/README +51 -0
- data/Rakefile +20 -0
- data/TODO +8 -0
- data/VERSION.yml +4 -0
- data/lib/dm-geokit.rb +5 -0
- data/lib/dm-geokit/ip_geocode_lookup.rb +35 -0
- data/lib/dm-geokit/resource.rb +237 -0
- data/lib/dm-geokit/support/distance_measurement.rb +16 -0
- data/lib/dm-geokit/support/distance_support.rb +11 -0
- data/lib/dm-geokit/support/float.rb +1 -0
- data/lib/dm-geokit/support/integer.rb +1 -0
- data/lib/dm-geokit/support/symbol.rb +11 -0
- data/lib/jeweler/templates/.gitignore +0 -0
- data/lib/skeleton/api_keys_template +50 -0
- metadata +101 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Matt King
|
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.
|
data/README
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
dm-geokit
|
2
|
+
=========
|
3
|
+
|
4
|
+
A mixin for Datamapper models that enables geographic functionality.
|
5
|
+
|
6
|
+
* Search for content via DataMapper-style query methods, e.g. Location.all(:address.near => {:origin => 'Portland, OR', :distance => 5.mi})
|
7
|
+
* Sort by distance easily: Location.all(:address.near => {:origin => 'Portland, OR', :distance => 5.mi}, :order => [:address_distance.desc])
|
8
|
+
* Ability to specify multiple fields that are geocodable (mostly)
|
9
|
+
|
10
|
+
Usage
|
11
|
+
=====
|
12
|
+
|
13
|
+
Basic Class Definition:
|
14
|
+
|
15
|
+
class Location
|
16
|
+
include DataMapper::Resource
|
17
|
+
property :id, Serial
|
18
|
+
has_geographic_location :address
|
19
|
+
end
|
20
|
+
|
21
|
+
This will automatically generate fields and methods for use with the DM Object, prefixed with the field name specified.
|
22
|
+
Since the above example used the field :address, the following fields would be generated:
|
23
|
+
|
24
|
+
* address_street_address
|
25
|
+
* address_city
|
26
|
+
* address_state
|
27
|
+
* address_zip
|
28
|
+
* address_country_code
|
29
|
+
* address_full_address
|
30
|
+
* address_lat
|
31
|
+
* address_lng
|
32
|
+
|
33
|
+
You can either reference those fields directly, or use the proxy object returned by calling .address on your object:
|
34
|
+
|
35
|
+
l = Location.all(:address.near => {:origin => 'Portland, OR', :distance => 5.mi})
|
36
|
+
|
37
|
+
l.each do |loc|
|
38
|
+
puts loc.address # .to_s yields string representation of full address, e.g. "12345 My St. Portland, OR USA"
|
39
|
+
puts loc.address.inspect # the proxy object, GeographicLocation, with matching methods for each property
|
40
|
+
puts loc.address.street_address # getting the street_address from the proxy object
|
41
|
+
puts loc.address_street_address # directly access the SQL column
|
42
|
+
end
|
43
|
+
|
44
|
+
The GeographicLocation proxy object is a convenience to allow you to compare and sort results in Ruby.
|
45
|
+
|
46
|
+
Requirements
|
47
|
+
===========
|
48
|
+
|
49
|
+
* geokit >= 1.5.0
|
50
|
+
* dm-core >= 0.10.1
|
51
|
+
* dm-aggregates >= 0.10.1
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |s|
|
4
|
+
s.name = 'dm-geokit'
|
5
|
+
s.summary = "DataMapper plugin for geokit stuff forked from Foy Savas's project. Now relies on the geokit gem rather than Foy's gem."
|
6
|
+
s.authors = ['Foy Savas', 'Daniel Higginbotham', 'Matt King']
|
7
|
+
s.email = 'matt@mattking.org'
|
8
|
+
s.homepage = "http://github.com/mattking17/dm-geokit/tree/master"
|
9
|
+
s.description = "Simple and opinionated helper for creating Rubygem projects on GitHub"
|
10
|
+
s.files = FileList["[A-Z]*", "{bin,generators,lib,test}/**/*", 'lib/jeweler/templates/.gitignore']
|
11
|
+
s.require_path = 'lib'
|
12
|
+
s.has_rdoc = true
|
13
|
+
s.platform = Gem::Platform::RUBY
|
14
|
+
s.extra_rdoc_files = %w[ README LICENSE TODO ]
|
15
|
+
s.add_dependency 'dm-core'
|
16
|
+
s.add_dependency 'andre-geokit'
|
17
|
+
end
|
18
|
+
rescue LoadError
|
19
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
20
|
+
end
|
data/TODO
ADDED
data/VERSION.yml
ADDED
data/lib/dm-geokit.rb
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
%w(rubygems geokit dm-core dm-aggregates).each{|f| require f}
|
2
|
+
%w(distance_measurement distance_support symbol integer float).each{|f|
|
3
|
+
require File.join(File.dirname(__FILE__),'dm-geokit','support',f)
|
4
|
+
}
|
5
|
+
require File.join(File.dirname(__FILE__),'dm-geokit','resource')
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module GeoKit
|
4
|
+
# Contains a class method geocode_ip_address which can be used to enable automatic geocoding
|
5
|
+
# for request IP addresses. The geocoded information is stored in a cookie and in the
|
6
|
+
# session to minimize web service calls. The point of the helper is to enable location-based
|
7
|
+
# websites to have a best-guess for new visitors.
|
8
|
+
module IpGeocodeLookup
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
# Places the IP address' geocode location into the session if it
|
13
|
+
# can be found. Otherwise, looks for a geo location cookie and
|
14
|
+
# uses that value. The last resort is to call the web service to
|
15
|
+
# get the value.
|
16
|
+
def store_ip_location
|
17
|
+
session[:geo_location] ||= retrieve_location_from_cookie_or_service
|
18
|
+
cookies[:geo_location] = { :value => session[:geo_location].to_yaml, :expires => 30.days.from_now } if session[:geo_location]
|
19
|
+
end
|
20
|
+
|
21
|
+
# Uses the stored location value from the cookie if it exists. If
|
22
|
+
# no cookie exists, calls out to the web service to get the location.
|
23
|
+
def retrieve_location_from_cookie_or_service
|
24
|
+
return YAML.load(cookies[:geo_location]) if cookies[:geo_location]
|
25
|
+
location = Geocoders::IpGeocoder.geocode(get_ip_address)
|
26
|
+
return location.success ? location : nil
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns the real ip address, though this could be the localhost ip
|
30
|
+
# address. No special handling here anymore.
|
31
|
+
def get_ip_address
|
32
|
+
request.remote_ip
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module GeoKit
|
3
|
+
PROPERTY_NAMES = %w(lat lng street_address city state zip country_code full_address)
|
4
|
+
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def has_geographic_location(name, options = {})
|
11
|
+
return if self.included_modules.include?(DataMapper::GeoKit::InstanceMethods)
|
12
|
+
send :include, InstanceMethods
|
13
|
+
send :include, ::GeoKit::Mappable
|
14
|
+
|
15
|
+
property name.to_sym, String, :length => 255
|
16
|
+
property "#{name}_distance".to_sym, Float
|
17
|
+
|
18
|
+
PROPERTY_NAMES.each do |p|
|
19
|
+
if p.match(/l(at|ng)/)
|
20
|
+
property "#{name}_#{p}".to_sym, Float, :precision => 15, :scale => 12, :index => true
|
21
|
+
else
|
22
|
+
property "#{name}_#{p}".to_sym, String, :length => 255
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
DataMapper.auto_upgrade!
|
27
|
+
|
28
|
+
if options[:auto_geocode] == true or options[:auto_geocode].nil?
|
29
|
+
define_method :auto_geocode? do
|
30
|
+
true
|
31
|
+
end
|
32
|
+
else
|
33
|
+
define_method :auto_geocode? do
|
34
|
+
false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
define_method "#{name}" do
|
39
|
+
if attribute_get(name.to_sym).nil?
|
40
|
+
nil
|
41
|
+
else
|
42
|
+
GeographicLocation.new(name, self)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
define_method "#{name}=" do |value|
|
47
|
+
if value.nil?
|
48
|
+
nil
|
49
|
+
elsif value.is_a?(String)
|
50
|
+
if auto_geocode?
|
51
|
+
geo = ::GeoKit::Geocoders::MultiGeocoder.geocode(value)
|
52
|
+
if geo.success?
|
53
|
+
attribute_set(name.to_sym, geo.full_address)
|
54
|
+
PROPERTY_NAMES.each do |p|
|
55
|
+
attribute_set("#{name}_#{p}".to_sym, geo.send(p.to_sym))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
else
|
59
|
+
attribute_set(name.to_sym, value)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
alias acts_as_mappable has_geographic_location
|
65
|
+
end
|
66
|
+
|
67
|
+
module InstanceMethods
|
68
|
+
def self.included(base) # :nodoc:
|
69
|
+
base.extend SingletonMethods
|
70
|
+
end
|
71
|
+
|
72
|
+
module SingletonMethods # :nodoc:
|
73
|
+
def all(query = {})
|
74
|
+
super(prepare_query(query))
|
75
|
+
end
|
76
|
+
|
77
|
+
def first(query = {})
|
78
|
+
super(prepare_query(query))
|
79
|
+
end
|
80
|
+
|
81
|
+
# Required dm-aggregates to work
|
82
|
+
def count(query = {})
|
83
|
+
super(prepare_query(query))
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
# Looks in the query for keys that are a DistanceOperator, then extracts the keys/values and turns them into conditions
|
89
|
+
def prepare_query(query)
|
90
|
+
query.each_pair do |k,v|
|
91
|
+
next if not k.is_a?(DistanceOperator)
|
92
|
+
field = k.target
|
93
|
+
origin = v[:origin].is_a?(String) ? ::GeoKit::Geocoders::MultiGeocoder.geocode(v[:origin]) : v[:origin]
|
94
|
+
distance = v[:distance]
|
95
|
+
query[:conditions] = expand_conditions(query[:conditions], "#{sphere_distance_sql(field, origin, distance.measurement)}", distance.to_f)
|
96
|
+
query[:conditions] = apply_bounds_conditions(query[:conditions], field, bounds_from_distance(distance.to_f, origin, distance.measurement))
|
97
|
+
query[:fields] = expand_fields(query[:fields], field, "#{sphere_distance_sql(field, origin, distance.measurement)}")
|
98
|
+
query.delete(k)
|
99
|
+
end
|
100
|
+
query
|
101
|
+
end
|
102
|
+
|
103
|
+
# Spherical distance sql
|
104
|
+
def sphere_distance_sql(field, origin, units)
|
105
|
+
lat = deg2rad(origin.lat)
|
106
|
+
lng = deg2rad(origin.lng)
|
107
|
+
qualified_lat_column = "`#{storage_name}`.`#{field}_lat`"
|
108
|
+
qualified_lng_column = "`#{storage_name}`.`#{field}_lng`"
|
109
|
+
"(ACOS(least(1,COS(#{lat})*COS(#{lng})*COS(RADIANS(#{qualified_lat_column}))*COS(RADIANS(#{qualified_lng_column}))+COS(#{lat})*SIN(#{lng})*COS(RADIANS(#{qualified_lat_column}))*SIN(RADIANS(#{qualified_lng_column}))+SIN(#{lat})*SIN(RADIANS(#{qualified_lat_column}))))*#{units_sphere_multiplier(units)})"
|
110
|
+
end
|
111
|
+
|
112
|
+
# in case conditions were altered by other means
|
113
|
+
def expand_conditions(conditions, sql, value)
|
114
|
+
if conditions.is_a?(Hash)
|
115
|
+
[conditions.keys.inject(''){|m,k|
|
116
|
+
m << "#{k} = ?"
|
117
|
+
} << " AND #{sql} <= ?"] + ([conditions.values] << value)
|
118
|
+
elsif conditions.is_a?(Array)
|
119
|
+
if conditions.size == 1
|
120
|
+
["#{conditions[0]} AND #{sql} <= ?", value]
|
121
|
+
else
|
122
|
+
conditions[0] = "#{conditions[0]} AND #{sql} <= ?"
|
123
|
+
conditions << value
|
124
|
+
conditions
|
125
|
+
end
|
126
|
+
else
|
127
|
+
["#{sql} <= ?", value]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Hack in the distance field by adding the :fields option to the query
|
132
|
+
def expand_fields(fields, distance_field, sql)
|
133
|
+
f = DataMapper::Property.new(self, "#{distance_field}_distance".to_sym, DataMapper::Types::Distance, :field => "#{sql} as #{distance_field}_distance")
|
134
|
+
if fields.is_a?(Array) # user specified fields, just tack this onto the end
|
135
|
+
fields + [f]
|
136
|
+
else # otherwise since we specify :fields, we have to add back in the original fields it would have selected
|
137
|
+
self.properties(repository.name).defaults + [f]
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def bounds_from_distance(distance, origin, units)
|
142
|
+
if distance
|
143
|
+
::GeoKit::Bounds.from_point_and_radius(origin,distance,:units=>units)
|
144
|
+
else
|
145
|
+
nil
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def apply_bounds_conditions(conditions, field, bounds)
|
150
|
+
qualified_lat_column = "`#{storage_name}`.`#{field}_lat`"
|
151
|
+
qualified_lng_column = "`#{storage_name}`.`#{field}_lng`"
|
152
|
+
sw, ne = bounds.sw, bounds.ne
|
153
|
+
lng_sql = bounds.crosses_meridian? ? "(#{qualified_lng_column}<=#{sw.lng} OR #{qualified_lng_column}>=#{ne.lng})" : "#{qualified_lng_column}>=#{sw.lng} AND #{qualified_lng_column}<=#{ne.lng}"
|
154
|
+
bounds_sql = "#{qualified_lat_column}>=#{sw.lat} AND #{qualified_lat_column}<=#{ne.lat} AND #{lng_sql}"
|
155
|
+
conditions[0] << " AND (#{bounds_sql})"
|
156
|
+
conditions
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
class GeographicLocation
|
163
|
+
attr_accessor :full_address, :lat, :lng, :street_address, :city, :state, :zip, :country_code, :distance
|
164
|
+
def initialize(field, obj)
|
165
|
+
PROPERTY_NAMES.each do |p|
|
166
|
+
instance_variable_set("@#{p}",obj.send("#{field}_#{p}"))
|
167
|
+
end
|
168
|
+
@distance = obj.send("#{field}_distance") if obj.respond_to?("#{field}_distance".to_sym)
|
169
|
+
end
|
170
|
+
def to_s
|
171
|
+
@full_address
|
172
|
+
end
|
173
|
+
def to_lat_lng
|
174
|
+
::GeoKit::LatLng.new(@lat,@lng)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
class DistanceOperator < DataMapper::Query::Operator
|
179
|
+
end
|
180
|
+
|
181
|
+
module DataObjectsAdapter
|
182
|
+
def self.included(base)
|
183
|
+
base.send(:include, SQL)
|
184
|
+
end
|
185
|
+
module SQL
|
186
|
+
def self.included(base)
|
187
|
+
base.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
188
|
+
# FIXME: figure out a cleaner approach than AMC
|
189
|
+
alias property_to_column_name_without_distance property_to_column_name
|
190
|
+
alias property_to_column_name property_to_column_name_with_distance
|
191
|
+
RUBY
|
192
|
+
end
|
193
|
+
|
194
|
+
def property_to_column_name_with_distance(property, qualify)
|
195
|
+
if property.is_a?(DataMapper::Property) and property.type == DataMapper::Types::Distance
|
196
|
+
property.field
|
197
|
+
else
|
198
|
+
property_to_column_name_without_distance(property, qualify)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
module Adapters
|
206
|
+
extendable do
|
207
|
+
# TODO: document
|
208
|
+
# @api private
|
209
|
+
def const_added(const_name)
|
210
|
+
if DataMapper::GeoKit.const_defined?(const_name)
|
211
|
+
adapter = const_get(const_name)
|
212
|
+
adapter.send(:include, DataMapper::GeoKit.const_get(const_name))
|
213
|
+
end
|
214
|
+
super
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
module Types
|
220
|
+
class Distance < DataMapper::Type
|
221
|
+
primitive Float
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
module Aggregates
|
226
|
+
module Model
|
227
|
+
def size
|
228
|
+
count
|
229
|
+
end
|
230
|
+
end
|
231
|
+
module Collection
|
232
|
+
def size
|
233
|
+
loaded? ? super : count
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class DistanceMeasurement
|
2
|
+
attr_accessor :measurement
|
3
|
+
def initialize(value,measurement)
|
4
|
+
@value = value.to_f
|
5
|
+
@measurement = measurement
|
6
|
+
end
|
7
|
+
def to_s
|
8
|
+
@value.to_s
|
9
|
+
end
|
10
|
+
def to_i
|
11
|
+
@value.to_i
|
12
|
+
end
|
13
|
+
def to_f
|
14
|
+
@value.to_f
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Float.send(:include, DistanceSupport)
|
@@ -0,0 +1 @@
|
|
1
|
+
Integer.send(:include, DistanceSupport)
|
File without changes
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# These defaults are used in GeoKit::Mappable.distance_to and in acts_as_mappable
|
2
|
+
GeoKit::default_units = :miles
|
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::timeout = 3
|
9
|
+
|
10
|
+
# These settings are used if web service calls must be routed through a proxy.
|
11
|
+
# These setting can be nil if not needed, otherwise, addr and port 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_addr = nil
|
15
|
+
GeoKit::Geocoders::proxy_port = nil
|
16
|
+
GeoKit::Geocoders::proxy_user = nil
|
17
|
+
GeoKit::Geocoders::proxy_pass = nil
|
18
|
+
|
19
|
+
# This is your yahoo application key for the Yahoo Geocoder.
|
20
|
+
# See http://developer.yahoo.com/faq/index.html#appid
|
21
|
+
# and http://developer.yahoo.com/maps/rest/V1/geocode.html
|
22
|
+
GeoKit::Geocoders::yahoo = 'REPLACE_WITH_YOUR_YAHOO_KEY'
|
23
|
+
|
24
|
+
# This is your Google Maps geocoder key.
|
25
|
+
# See http://www.google.com/apis/maps/signup.html
|
26
|
+
# and http://www.google.com/apis/maps/documentation/#Geocoding_Examples
|
27
|
+
GeoKit::Geocoders::google = 'REPLACE_WITH_YOUR_GOOGLE_KEY'
|
28
|
+
|
29
|
+
# This is your username and password for geocoder.us.
|
30
|
+
# To use the free service, the value can be set to nil or false. For
|
31
|
+
# usage tied to an account, the value should be set to username:password.
|
32
|
+
# See http://geocoder.us
|
33
|
+
# and http://geocoder.us/user/signup
|
34
|
+
GeoKit::Geocoders::geocoder_us = false
|
35
|
+
|
36
|
+
# This is your authorization key for geocoder.ca.
|
37
|
+
# To use the free service, the value can be set to nil or false. For
|
38
|
+
# usage tied to an account, set the value to the key obtained from
|
39
|
+
# Geocoder.ca.
|
40
|
+
# See http://geocoder.ca
|
41
|
+
# and http://geocoder.ca/?register=1
|
42
|
+
GeoKit::Geocoders::geocoder_ca = false
|
43
|
+
|
44
|
+
# This is the order in which the geocoders are called in a failover scenario
|
45
|
+
# If you only want to use a single geocoder, put a single symbol in the array.
|
46
|
+
# Valid symbols are :google, :yahoo, :us, and :ca.
|
47
|
+
# Be aware that there are Terms of Use restrictions on how you can use the
|
48
|
+
# various geocoders. Make sure you read up on relevant Terms of Use for each
|
49
|
+
# geocoder you are going to use.
|
50
|
+
GeoKit::Geocoders::provider_order = [:google,:us]
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dm-geokit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.10.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matt King
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-25 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: dm-core
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.10.1
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: geokit
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.5.0
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: dm-aggregates
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.10.1
|
44
|
+
version:
|
45
|
+
description: Adds geographic functionality to DataMapper objects
|
46
|
+
email: matt@mattking.org
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- README
|
53
|
+
- LICENSE
|
54
|
+
- TODO
|
55
|
+
files:
|
56
|
+
- LICENSE
|
57
|
+
- Rakefile
|
58
|
+
- README
|
59
|
+
- TODO
|
60
|
+
- VERSION.yml
|
61
|
+
- lib/dm-geokit
|
62
|
+
- lib/dm-geokit/ip_geocode_lookup.rb
|
63
|
+
- lib/dm-geokit/resource.rb
|
64
|
+
- lib/dm-geokit.rb
|
65
|
+
- lib/skeleton
|
66
|
+
- lib/skeleton/api_keys_template
|
67
|
+
- lib/jeweler/templates/.gitignore
|
68
|
+
- lib/dm-geokit/support/distance_measurement.rb
|
69
|
+
- lib/dm-geokit/support/distance_support.rb
|
70
|
+
- lib/dm-geokit/support/float.rb
|
71
|
+
- lib/dm-geokit/support/integer.rb
|
72
|
+
- lib/dm-geokit/support/symbol.rb
|
73
|
+
has_rdoc: true
|
74
|
+
homepage: http://github.com/mattking17/dm-geokit/tree/master
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options:
|
77
|
+
- --inline-source
|
78
|
+
- --charset=UTF-8
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: "0"
|
86
|
+
version:
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: "0"
|
92
|
+
version:
|
93
|
+
requirements: []
|
94
|
+
|
95
|
+
rubyforge_project: dm-geokit
|
96
|
+
rubygems_version: 1.3.1
|
97
|
+
signing_key:
|
98
|
+
specification_version: 2
|
99
|
+
summary: Adds geographic functionality to DataMapper objects, relying on the Geokit gem for geocoding and searching by geographic location.
|
100
|
+
test_files: []
|
101
|
+
|