urban-mapping-api 0.9.3
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/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +82 -0
- data/Rakefile +56 -0
- data/VERSION +1 -0
- data/lib/core_ext.rb +39 -0
- data/lib/urban-mapping-api.rb +136 -0
- data/test/test_helper.rb +10 -0
- data/test/urban-mapping-api_test.rb +7 -0
- data/urban-mapping-api.gemspec +55 -0
- metadata +76 -0
data/.document
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Michael Dwan
|
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.rdoc
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
= urban-mapping-api
|
2
|
+
|
3
|
+
A simple ruby interface to Urban Mapping's free and premium neighborhood lookup API.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
sudo gem install michaeldwan-urban-mapping-api
|
8
|
+
|
9
|
+
Gem dependencies:
|
10
|
+
|
11
|
+
* curb
|
12
|
+
* json
|
13
|
+
|
14
|
+
== Examples
|
15
|
+
|
16
|
+
To get started you need to require 'urban-mapping-api':
|
17
|
+
|
18
|
+
% irb -rubygems
|
19
|
+
irb(main):001:0> require 'urban-mapping-api'
|
20
|
+
# => true
|
21
|
+
|
22
|
+
Before you do anything, create an instance of UrbanMapping::Interface
|
23
|
+
|
24
|
+
interface = UrbanMapping::Interface.new('my-api-key')
|
25
|
+
|
26
|
+
For premium API access, include the premium API key
|
27
|
+
|
28
|
+
interface = UrbanMapping::Interface.new('my-api-key', :shared_secret => 'my-shared-secred')
|
29
|
+
interface.premium_api?
|
30
|
+
# => true
|
31
|
+
|
32
|
+
The default return value of all methods is an OpenStruct or array of OpenStructs.
|
33
|
+
|
34
|
+
interface = UrbanMapping::Interface.new('my-api-key')
|
35
|
+
hood = interface.get_neighborhood_detail(3094847)
|
36
|
+
hood
|
37
|
+
# => #<OpenStruct city="Chicago", name="The Loop", state="IL", ...>
|
38
|
+
hood.city
|
39
|
+
# => "Chicago"
|
40
|
+
|
41
|
+
If you want the raw hash output, pass :raw => true to the constructor
|
42
|
+
|
43
|
+
interface = UrbanMapping::Interface.new('my-api-key', :shared_secret => 'my-shared-secred', :raw => true)
|
44
|
+
hood = interface.get_neighborhood_detail(3094847)
|
45
|
+
hood
|
46
|
+
# => {"wkt_centroid"=>"POINT(-87.6260772332496 41.8782770670931)", "name"=>"The Loop", "city"=>"Chicago"...
|
47
|
+
hood.city
|
48
|
+
# => "Chicago"
|
49
|
+
|
50
|
+
(If you don't have an api key, go get one at http://developer.urbanmapping.com/accounts/register/)
|
51
|
+
|
52
|
+
Now that you have an instance of the interface, you can make calls to the service. (The below examples are using raw output.)
|
53
|
+
|
54
|
+
interface.get_neighborhoods_by_postal_code('60654')
|
55
|
+
# => [{"name"=>"River North", "city"=>"Chicago", "country"=>"USA", "id"=>3320072, "state"=>"IL"}, ...]
|
56
|
+
|
57
|
+
interface.get_neighborhoods_by_lat_lng(41.882088, -87.624454)
|
58
|
+
# => [{"name"=>"The Loop", "city"=>"Chicago", "country"=>"USA", "id"=>3094847, "state"=>"IL"}]
|
59
|
+
|
60
|
+
interface.get_neighborhood_detail(3094847)
|
61
|
+
# => {"wkt_centroid"=>"POINT(-87.6260772332496 41.8782770670931)", "name"=>"The Loop", "city"=>"Chicago"...
|
62
|
+
|
63
|
+
== Helpful Links
|
64
|
+
|
65
|
+
* urban-mapping-api Gem documentation http://rdoc.info/projects/michaeldwan/urban-mapping-api
|
66
|
+
* Urban Mapping http://www.urbanmapping.com/urbanware/neighborhood-database/index.html
|
67
|
+
* Api Documentation http://developer.urbanmapping.com/docs/neighborhoods
|
68
|
+
* Register for a free API key http://developer.urbanmapping.com/accounts/register
|
69
|
+
|
70
|
+
== Note on Patches/Pull Requests
|
71
|
+
|
72
|
+
* Fork the project.
|
73
|
+
* Make your feature addition or bug fix.
|
74
|
+
* Add tests for it. This is important so I don't break it in a
|
75
|
+
future version unintentionally.
|
76
|
+
* Commit, do not mess with rakefile, version, or history.
|
77
|
+
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
78
|
+
* Send me a pull request. Bonus points for topic branches.
|
79
|
+
|
80
|
+
== Copyright
|
81
|
+
|
82
|
+
Copyright (c) 2009 Michael Dwan. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "urban-mapping-api"
|
8
|
+
gem.summary = "A simple ruby interface to Urban Mapping's free and premium neighborhood lookup API"
|
9
|
+
gem.description = "A simple ruby interface to Urban Mapping's free and premium neighborhood lookup API"
|
10
|
+
gem.email = "mpdwan@gmail.com"
|
11
|
+
gem.homepage = "http://github.com/michaeldwan/urban-mapping-api"
|
12
|
+
gem.authors = ["Michael Dwan"]
|
13
|
+
gem.add_development_dependency "thoughtbot-shoulda"
|
14
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
|
+
end
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/testtask'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib' << 'test'
|
23
|
+
test.pattern = 'test/**/*_test.rb'
|
24
|
+
test.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.pattern = 'test/**/*_test.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
task :test => :check_dependencies
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rake/rdoctask'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
if File.exist?('VERSION')
|
47
|
+
version = File.read('VERSION')
|
48
|
+
else
|
49
|
+
version = ""
|
50
|
+
end
|
51
|
+
|
52
|
+
rdoc.rdoc_dir = 'rdoc'
|
53
|
+
rdoc.title = "urban-mapping-api #{version}"
|
54
|
+
rdoc.rdoc_files.include('README*')
|
55
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.9.3
|
data/lib/core_ext.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
class Object
|
2
|
+
def to_openstruct
|
3
|
+
self
|
4
|
+
end
|
5
|
+
|
6
|
+
module InstanceExecHelper; end
|
7
|
+
|
8
|
+
include InstanceExecHelper
|
9
|
+
def instance_exec(*args, &block)
|
10
|
+
begin
|
11
|
+
old_critical, Thread.critical = Thread.critical, true
|
12
|
+
n = 0
|
13
|
+
n += 1 while respond_to?(mname="__instance_exec#{n}")
|
14
|
+
InstanceExecHelper.module_eval{ define_method(mname, &block) }
|
15
|
+
ensure
|
16
|
+
Thread.critical = old_critical
|
17
|
+
end
|
18
|
+
begin
|
19
|
+
ret = send(mname, *args)
|
20
|
+
ensure
|
21
|
+
InstanceExecHelper.module_eval{ remove_method(mname) } rescue nil
|
22
|
+
end
|
23
|
+
ret
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Array
|
28
|
+
def to_openstruct
|
29
|
+
map{ |el| el.to_openstruct }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Hash
|
34
|
+
def to_openstruct
|
35
|
+
mapped = {}
|
36
|
+
each{ |key,value| mapped[key] = value.to_openstruct }
|
37
|
+
UrbanMapping::NeighborhoodOpenStruct.new(mapped)
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'curl'
|
2
|
+
require 'json'
|
3
|
+
require 'digest'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'uri'
|
6
|
+
require "#{File.dirname(__FILE__)}/core_ext"
|
7
|
+
|
8
|
+
module UrbanMapping
|
9
|
+
class RequestError < StandardError
|
10
|
+
attr_reader :code, :url, :message
|
11
|
+
def initialize(code, url, message)
|
12
|
+
@code = code
|
13
|
+
@url = url
|
14
|
+
@message = message
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class NeighborhoodOpenStruct < OpenStruct
|
19
|
+
def id
|
20
|
+
@table[:id] || super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Interface
|
25
|
+
ENDPOINT = 'http://api1.urbanmapping.com/neighborhoods/rest'
|
26
|
+
|
27
|
+
attr_reader :api_key, :shared_secret, :options3
|
28
|
+
|
29
|
+
# Create a new instance.
|
30
|
+
# Requeres an api_key. A shared key needs to be provided for
|
31
|
+
# access to premium API methods.
|
32
|
+
def initialize(api_key, options = {})
|
33
|
+
options = {
|
34
|
+
:raw => false
|
35
|
+
}.merge(options)
|
36
|
+
@api_key = api_key
|
37
|
+
@shared_secret = options.delete(:shared_secret)
|
38
|
+
@options = options
|
39
|
+
end
|
40
|
+
|
41
|
+
# Returns true if a shard_secret was provided to the constructor.
|
42
|
+
def premium_api?
|
43
|
+
!shared_secret.nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
# Returns a list of neighborhoods whose boundaries contain the requested
|
47
|
+
# latitude and longitude.
|
48
|
+
def get_neighborhoods_by_lat_lng(latitude, longitude)
|
49
|
+
perform('getNeighborhoodsByLatLng', :lat => latitude, :lng => longitude)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Returns the neighborhood whose centroid is nearest to the requested
|
53
|
+
# latitude and longitude within a 20 linear mile range.
|
54
|
+
def get_nearest_neighborhood(latitude, longitude)
|
55
|
+
perform('getNearestNeighborhood', :lat => latitude, :lng => longitude)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Returns a list of neighborhoods within a bounding box extent defined by
|
59
|
+
# southwestern and northeastern corners. Note query extents covering more
|
60
|
+
# than 45 square miles will be rejected.
|
61
|
+
def get_neighborhoods_by_extent(southwest_latitude, southwest_longitude, northeast_latitude, northeast_longitude)
|
62
|
+
perform('getNeighborhoodsByExtent', :swlat => southwest_latitude,
|
63
|
+
:swlng => southwest_longitude,
|
64
|
+
:nelat => northeast_latitude,
|
65
|
+
:nelng => northeast_longitude)
|
66
|
+
end
|
67
|
+
|
68
|
+
# This method first geocodes the input address, then returns the geocode
|
69
|
+
# and lists neighborhoods containing the point in a single response.
|
70
|
+
# This is technically executed in a single request, but for the purposes
|
71
|
+
# of account administration a single invocation is counted as two calls.
|
72
|
+
def get_neighborhoods_by_address(street, city, state, country = 'USA')
|
73
|
+
perform('getNeighborhoodsByAddress', :street => street,
|
74
|
+
:city => city,
|
75
|
+
:state => state,
|
76
|
+
:country => country)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns a list of neighborhood for the requested city.
|
80
|
+
def get_neighborhoods_by_city_state_country(city, state, country = 'USA')
|
81
|
+
perform('getNeighborhoodsByCityStateCountry', :city => city,
|
82
|
+
:state => state,
|
83
|
+
:country => country)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns a list of neighborhoods whose areas intersect that of the requested postal code.
|
87
|
+
def get_neighborhoods_by_postal_code(postal_code)
|
88
|
+
perform('getNeighborhoodsByPostalCode', :postalCode => postal_code)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Returns a list of neighborhoods for the requested neighborhood name.
|
92
|
+
def get_neighborhoods_by_name(name)
|
93
|
+
perform('getNeighborhoodsByName', :name => name)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Returns neighborhood details for the requested neighborhood ID.
|
97
|
+
def get_neighborhood_detail(id)
|
98
|
+
perform('getNeighborhoodDetail', :neighborhoodId => id)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns neighborhood relationship attributes for the requested neighborhood ID.
|
102
|
+
def get_neighborhood_relationships(id)
|
103
|
+
perform('getNeighborhoodRelationships', :neighborhoodId => id)
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
def generate_signature
|
108
|
+
Digest::MD5.hexdigest([api_key, shared_secret, Time.now.utc.to_i.to_s].join)
|
109
|
+
end
|
110
|
+
|
111
|
+
def perform(method, parameters)
|
112
|
+
parameters.merge!({
|
113
|
+
:format => 'json',
|
114
|
+
:apikey => api_key
|
115
|
+
})
|
116
|
+
parameters.merge!(:sig => generate_signature) if premium_api?
|
117
|
+
|
118
|
+
query_string = parameters.to_a.map{ |x| x.map{|val| URI.encode(val.to_s)}.join('=') }.join('&')
|
119
|
+
|
120
|
+
url = "#{ENDPOINT}/#{method}?#{query_string}"
|
121
|
+
response = Curl::Easy.perform(url)
|
122
|
+
|
123
|
+
if response.response_code != 200
|
124
|
+
raise RequestError.new(response.response_code, url, response.body_str)
|
125
|
+
end
|
126
|
+
|
127
|
+
output = JSON.parse(response.body_str)
|
128
|
+
|
129
|
+
return output if options[:raw]
|
130
|
+
|
131
|
+
output.to_openstruct
|
132
|
+
rescue StandardError => ex
|
133
|
+
raise "An error occured while calling #{url}: #{ex.message}\n#{ex.backtrace}"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{urban-mapping-api}
|
8
|
+
s.version = "0.9.3"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Michael Dwan"]
|
12
|
+
s.date = %q{2009-12-02}
|
13
|
+
s.description = %q{A simple ruby interface to Urban Mapping's free and premium neighborhood lookup API}
|
14
|
+
s.email = %q{mpdwan@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".gitignore",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"lib/core_ext.rb",
|
27
|
+
"lib/urban-mapping-api.rb",
|
28
|
+
"test/test_helper.rb",
|
29
|
+
"test/urban-mapping-api_test.rb",
|
30
|
+
"urban-mapping-api.gemspec"
|
31
|
+
]
|
32
|
+
s.homepage = %q{http://github.com/michaeldwan/urban-mapping-api}
|
33
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
34
|
+
s.require_paths = ["lib"]
|
35
|
+
s.rubygems_version = %q{1.3.5}
|
36
|
+
s.summary = %q{A simple ruby interface to Urban Mapping's free and premium neighborhood lookup API}
|
37
|
+
s.test_files = [
|
38
|
+
"test/test_helper.rb",
|
39
|
+
"test/urban-mapping-api_test.rb"
|
40
|
+
]
|
41
|
+
|
42
|
+
if s.respond_to? :specification_version then
|
43
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
44
|
+
s.specification_version = 3
|
45
|
+
|
46
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
47
|
+
s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
48
|
+
else
|
49
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
50
|
+
end
|
51
|
+
else
|
52
|
+
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: urban-mapping-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Dwan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-02 00:00:00 -06:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: thoughtbot-shoulda
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description: A simple ruby interface to Urban Mapping's free and premium neighborhood lookup API
|
26
|
+
email: mpdwan@gmail.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- LICENSE
|
33
|
+
- README.rdoc
|
34
|
+
files:
|
35
|
+
- .document
|
36
|
+
- .gitignore
|
37
|
+
- LICENSE
|
38
|
+
- README.rdoc
|
39
|
+
- Rakefile
|
40
|
+
- VERSION
|
41
|
+
- lib/core_ext.rb
|
42
|
+
- lib/urban-mapping-api.rb
|
43
|
+
- test/test_helper.rb
|
44
|
+
- test/urban-mapping-api_test.rb
|
45
|
+
- urban-mapping-api.gemspec
|
46
|
+
has_rdoc: true
|
47
|
+
homepage: http://github.com/michaeldwan/urban-mapping-api
|
48
|
+
licenses: []
|
49
|
+
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options:
|
52
|
+
- --charset=UTF-8
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
requirements: []
|
68
|
+
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 1.3.5
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: A simple ruby interface to Urban Mapping's free and premium neighborhood lookup API
|
74
|
+
test_files:
|
75
|
+
- test/test_helper.rb
|
76
|
+
- test/urban-mapping-api_test.rb
|