DCGOV 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +21 -0
- data/README +29 -0
- data/Rakefile +52 -0
- data/lib/dcgov.rb +19 -0
- data/lib/dcgov/address.rb +48 -0
- data/lib/dcgov/easy_class_maker.rb +45 -0
- data/lib/dcgov/geocoder.rb +60 -0
- data/lib/dcgov/open311.rb +36 -0
- data/lib/dcgov/service_request.rb +40 -0
- data/lib/dcgov/service_request_field.rb +25 -0
- data/lib/dcgov/service_type.rb +16 -0
- data/lib/dcgov/util.rb +42 -0
- data/spec/geocoder_spec.rb +42 -0
- data/spec/open_311_spec.rb +41 -0
- data/spec/spec_helper.rb +23 -0
- metadata +78 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
== DC311
|
2
|
+
|
3
|
+
Copyright (c) 2009 Zvi Band and skeevisArts LLC
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
= DC Government GeoCoder and 311 API
|
2
|
+
|
3
|
+
... a ruby gem for the not-yet-complete API published by the DC OCTO
|
4
|
+
|
5
|
+
== Install
|
6
|
+
|
7
|
+
sudo gem install dcgov
|
8
|
+
|
9
|
+
== Example
|
10
|
+
|
11
|
+
Here's a quick example of how you could use it.
|
12
|
+
|
13
|
+
require 'rubygems'
|
14
|
+
require 'dcgov'
|
15
|
+
results = DCGOV::GeoCoder.get({:address=>"441 4th str, nw"})
|
16
|
+
print results.inspect
|
17
|
+
|
18
|
+
== Usage
|
19
|
+
|
20
|
+
Honestly, I haven't had a chance yet. But I will say this. If you go into the spec directory you'll find tests for the geocoder and open_311 APIs.
|
21
|
+
The rspec tests
|
22
|
+
|
23
|
+
If you feel like helping out, expand this readme for me :-)
|
24
|
+
|
25
|
+
Zvi Band, 2009
|
26
|
+
zvi@skeevisarts.com
|
27
|
+
http://skeevisarts.com
|
28
|
+
|
29
|
+
@skeevis on the twitter.
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
#
|
2
|
+
# To change this template, choose Tools | Templates
|
3
|
+
# and open the template in the editor.
|
4
|
+
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'rake'
|
8
|
+
require 'rake/clean'
|
9
|
+
require 'rake/gempackagetask'
|
10
|
+
require 'rake/rdoctask'
|
11
|
+
require 'rake/testtask'
|
12
|
+
require 'spec/rake/spectask'
|
13
|
+
|
14
|
+
spec = Gem::Specification.new do |s|
|
15
|
+
s.name = 'DCGOV'
|
16
|
+
s.version = '0.0.1'
|
17
|
+
s.has_rdoc = true
|
18
|
+
s.extra_rdoc_files = ['README', 'LICENSE']
|
19
|
+
s.summary = 'A basic interface to the citywide API published by the District of Columbia'
|
20
|
+
s.description = s.summary
|
21
|
+
s.author = 'Zvi Band'
|
22
|
+
s.email = 'zvi@skeevisarts.com'
|
23
|
+
s.homepage = 'http://skeevisarts.com'
|
24
|
+
# s.executables = ['your_executable_here']
|
25
|
+
s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib,spec}/**/*")
|
26
|
+
s.require_path = "lib"
|
27
|
+
s.bindir = "bin"
|
28
|
+
s.add_dependency("json")
|
29
|
+
end
|
30
|
+
|
31
|
+
Rake::GemPackageTask.new(spec) do |p|
|
32
|
+
p.gem_spec = spec
|
33
|
+
p.need_tar = true
|
34
|
+
p.need_zip = true
|
35
|
+
end
|
36
|
+
|
37
|
+
Rake::RDocTask.new do |rdoc|
|
38
|
+
files =['README', 'LICENSE', 'lib/**/*.rb']
|
39
|
+
rdoc.rdoc_files.add(files)
|
40
|
+
rdoc.main = "README" # page to start on
|
41
|
+
rdoc.title = "DCGOV Docs"
|
42
|
+
rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
|
43
|
+
rdoc.options << '--line-numbers'
|
44
|
+
end
|
45
|
+
|
46
|
+
Rake::TestTask.new do |t|
|
47
|
+
t.test_files = FileList['test/**/*.rb']
|
48
|
+
end
|
49
|
+
|
50
|
+
Spec::Rake::SpecTask.new do |t|
|
51
|
+
t.spec_files = FileList['spec/**/*.rb']
|
52
|
+
end
|
data/lib/dcgov.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'cgi'
|
3
|
+
require 'net/http'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
$:.unshift(File.dirname(__FILE__))
|
8
|
+
require 'dcgov/easy_class_maker'
|
9
|
+
require 'dcgov/geocoder'
|
10
|
+
require 'dcgov/open311'
|
11
|
+
require 'dcgov/service_request_field'
|
12
|
+
require 'dcgov/service_type'
|
13
|
+
require 'dcgov/address'
|
14
|
+
require 'dcgov/util'
|
15
|
+
|
16
|
+
module DCGOV
|
17
|
+
#Not too much in here...
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module DCGOV
|
2
|
+
class Address
|
3
|
+
include EasyClassMaker
|
4
|
+
|
5
|
+
# just a sample of what dc returns, for reference purposes.
|
6
|
+
# [{"aid"=>"285552"}, {"status"=>"ACTIVE"}, {"fulladdress"=>"441 4TH STREET NW"}, {"addrnum"=>"441"}, {"stname"=>"4TH"}, {"street_type"=>"STREET"},
|
7
|
+
# {"quadrant"=>"NW"}, {"city"=>"WASHINGTON"}, {"state"=>"DC"}, {"xcoord"=>"398642.18"}, {"ycoord"=>"136399.84"},
|
8
|
+
# {"ssl"=>"0532 0020"}, {"anc"=>"ANC 6C"}, {"psa"=>"Police Service Area 101"}, {"ward"=>"Ward 6"}, {"nbhd_action"=>" "},
|
9
|
+
# {"cluster"=>"Cluster 8"}, {"poldist"=>"Police District - First District"}, {"roc"=>"-"}, {"census_tract"=>"59"},
|
10
|
+
# {"vote_prcnct"=>"Precinct 143"}, {"smd"=>"SMD02 6C09"}, {"zipcode"=>"20001"}, {"latitude"=>"38.89544591"},
|
11
|
+
# {"longitude"=>"-77.01565221"}, {"distance"=>"0"}]
|
12
|
+
|
13
|
+
attributes :aid,:status,:fulladdress,:addrnum,:stname,:street_type,:quadrant,:city,:state,:xoord,:ycoord,:ssl,:anc,:psa,:ward,:nbhd,:clust,:poldist,:roc,:census_tract,
|
14
|
+
:vote_prcnct,:smd,:zipcode,:latitude,:longitude,:distance
|
15
|
+
|
16
|
+
# Creates a new user from a piece of xml
|
17
|
+
def self.new_from_hash(hsh)
|
18
|
+
u = new
|
19
|
+
u.aid = hsh['aid']
|
20
|
+
u.status = hsh['status']
|
21
|
+
u.fulladdress = hsh['fulladdress']
|
22
|
+
u.addrnum = hsh['addrnum']
|
23
|
+
u.stname = hsh['stname']
|
24
|
+
u.street_type = hsh['street_type']
|
25
|
+
u.quadrant = hsh['quadrant']
|
26
|
+
u.city = hsh['city']
|
27
|
+
u.state = hsh['state']
|
28
|
+
u.xoord = hsh['xoord']
|
29
|
+
u.ycoord = hsh['ycoord']
|
30
|
+
u.ssl = hsh['ssl']
|
31
|
+
u.anc = hsh['anc']
|
32
|
+
u.psa = hsh['psa']
|
33
|
+
u.ward = hsh['ward']
|
34
|
+
u.nbhd = hsh['nbhd']
|
35
|
+
u.clust = hsh['clust']
|
36
|
+
u.poldist = hsh['poldist']
|
37
|
+
u.roc = hsh['roc']
|
38
|
+
u.census_tract = hsh['census_tract']
|
39
|
+
u.vote_prcnct = hsh['vote_prcnct']
|
40
|
+
u.smd = hsh['smd']
|
41
|
+
u.zipcode = hsh['zipcode']
|
42
|
+
u.latitude = hsh['latitude']
|
43
|
+
u.longitude = hsh['longitude']
|
44
|
+
u.distance = hsh['distance']
|
45
|
+
u
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# This is pretty much just a macro for creating a class that allows
|
2
|
+
# using a block to initialize stuff and to define getters and setters
|
3
|
+
# really quickly.
|
4
|
+
#
|
5
|
+
# I stole this from the Twitter gem. Who knows who they stole it from.
|
6
|
+
module DCGOV
|
7
|
+
module EasyClassMaker
|
8
|
+
|
9
|
+
def self.included(base)
|
10
|
+
base.extend(ClassMethods)
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
# creates the attributes class variable and creates each attribute's accessor methods
|
15
|
+
def attributes(*attrs)
|
16
|
+
@@attributes = attrs
|
17
|
+
@@attributes.each { |a| attr_accessor a }
|
18
|
+
end
|
19
|
+
|
20
|
+
# read method for attributes class variable
|
21
|
+
def self.attributes; @@attributes end
|
22
|
+
end
|
23
|
+
|
24
|
+
# allows for any class that includes this to use a block to initialize
|
25
|
+
# variables instead of assigning each one seperately
|
26
|
+
#
|
27
|
+
# Example:
|
28
|
+
#
|
29
|
+
# instead of...
|
30
|
+
#
|
31
|
+
# s = Status.new
|
32
|
+
# s.foo = 'thing'
|
33
|
+
# s.bar = 'another thing'
|
34
|
+
#
|
35
|
+
# you can ...
|
36
|
+
#
|
37
|
+
# Status.new do |s|
|
38
|
+
# s.foo = 'thing'
|
39
|
+
# s.bar = 'another thing'
|
40
|
+
# end
|
41
|
+
def initialize
|
42
|
+
yield self if block_given?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module DCGOV
|
2
|
+
class GeoCoder
|
3
|
+
#master dispatcher
|
4
|
+
def self.get(options)
|
5
|
+
if options[:address]
|
6
|
+
find_by_address(options[:address])
|
7
|
+
elsif options[:lat] && options[:lon]
|
8
|
+
find_by_lat_lon(options[:lat],options[:lon])
|
9
|
+
elsif options[:mar_id]
|
10
|
+
find_by_id(options[:mar_id])
|
11
|
+
else
|
12
|
+
nil #dumbass.
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
#do a search via latitude and longitude.
|
18
|
+
def self.find_by_lat_lon(lat,lon)
|
19
|
+
begin
|
20
|
+
request_url = "/geocoding/v1/getFromLatLong.json?lat=#{CGI::escape(lat)}&long=#{CGI::escape(lon)}"
|
21
|
+
result_json = DCGOV::Util.pull_from_json(request_url)
|
22
|
+
return result_json["addresses"].collect { |address| DCGOV::Address.new_from_hash(address["address"][0]) }
|
23
|
+
rescue
|
24
|
+
#crap, something went wrong
|
25
|
+
return nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
#find via a normal street address... "1600 pennsylvania"
|
31
|
+
def self.find_by_address(address)
|
32
|
+
begin
|
33
|
+
request_url = "/geocoding/v1/search.json?address=#{CGI::escape(address)}"
|
34
|
+
result_json = DCGOV::Util.pull_from_json(request_url)
|
35
|
+
return result_json["addresses"].collect { |address| DCGOV::Address.new_from_hash(address["address"][0]) }
|
36
|
+
rescue
|
37
|
+
#crap, something went wrong
|
38
|
+
return nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
#find by a mar ID
|
43
|
+
def self.find_by_id(mar_id)
|
44
|
+
begin
|
45
|
+
request_url = "/geocoding/v1/get.json?aid=#{mar_id}"
|
46
|
+
result_json = DCGOV::Util.pull_from_json(request_url)
|
47
|
+
return DCGOV::Address.new_from_hash(result_json["address"][0])
|
48
|
+
rescue
|
49
|
+
#crap, something went wrong
|
50
|
+
return nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# just so I could make sure rspec was working.
|
55
|
+
def self.foo
|
56
|
+
"bar"
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module DCGOV
|
2
|
+
class Open311
|
3
|
+
def self.get_service_types()
|
4
|
+
request_url = "/open311/v1/meta_getTypesList.json"
|
5
|
+
result_json = DCGOV::Util.pull_from_json(request_url)
|
6
|
+
return result_json["servicetypeslist"].collect { |st| DCGOV::ServiceType.new_from_hash(st["servicetype"]) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.get_request_fields(sr_id)
|
10
|
+
request_url = "/open311/v1/meta_getTypeDefinition.json?servicecode=#{CGI::escape(sr_id)}"
|
11
|
+
result_json = DCGOV::Util.pull_from_json(request_url)
|
12
|
+
#print result_json.inspect
|
13
|
+
return result_json["servicetypedefinition"].collect { |st| DCGOV::ServiceRequestField.new_from_hash(st["servicetype"]) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.get(request_id)
|
17
|
+
request_url = "/open311/v1/get.json?servicerequestid=#{CGI::escape(request_id)}"
|
18
|
+
result_json = DCGOV::Util.pull_from_json(request_url)
|
19
|
+
results_fixed = DCGOV::Util::fix_hash(result_json["servicerequest"])
|
20
|
+
return results_fixed
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.resolve_token(token_id)
|
24
|
+
request_url = "/open311/v1/getFromToken.json?token=#{token_id}"
|
25
|
+
result_json = DCGOV::Util.pull_from_json(request_url)
|
26
|
+
result_json["servicerequestid"]
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.submit(values)
|
30
|
+
request_url = "/open311/v1/submit.json"
|
31
|
+
result_json = DCGOV::Util.post_to_json(values,request_url)
|
32
|
+
result_json["token"]
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module DCGOV
|
2
|
+
class ServiceRequest
|
3
|
+
|
4
|
+
include EasyClassMaker
|
5
|
+
|
6
|
+
attributes :anc,:lattitude,:serviceorderdate,:resolution,:servicerequestid,:siteaddress,:serviceorderstatus,:district,:zipcode,:servicenotes,:servicetypecodedescription,:servicecodedescription,:servicecode,:neighborhoodcluster,:servicepriority,:aid,:serviceduedate,:resolutiondate,:psa,:longitude,:smd,:ward,:agencyabbreviation,:servicetypeocde
|
7
|
+
|
8
|
+
# Creates a new user from a piece of xml
|
9
|
+
def self.new_from_hash(hsh)
|
10
|
+
u = new
|
11
|
+
u.anc = hsh['anc']
|
12
|
+
u.lattitude = hsh['lattitude']
|
13
|
+
u.serviceorderdate = hsh['serviceorderdate']
|
14
|
+
u.resolution = hsh['resolution']
|
15
|
+
u.servicerequestid = hsh['servicerequestid']
|
16
|
+
u.siteaddress = hsh['siteaddress']
|
17
|
+
u.serviceorderstatus = hsh['serviceorderstatus']
|
18
|
+
u.district = hsh['district']
|
19
|
+
u.zipcode = hsh['zipcode']
|
20
|
+
u.servicenotes = hsh['servicenotes']
|
21
|
+
u.servicetypecodedescription = hsh['servicetypecodedescription']
|
22
|
+
u.servicecodedescription = hsh['servicecodedescription']
|
23
|
+
u.servicecode = hsh['servicecode']
|
24
|
+
u.neighborhoodcluster = hsh['neighborhoodcluster']
|
25
|
+
u.servicepriority = hsh['servicepriority']
|
26
|
+
u.aid = hsh['aid']
|
27
|
+
u.serviceduedate = hsh['serviceduedate']
|
28
|
+
u.resolutiondate = hsh['resolutiondate']
|
29
|
+
u.psa = hsh['psa']
|
30
|
+
u.longitude = hsh['longitude']
|
31
|
+
u.smd = hsh['smd']
|
32
|
+
u.ward = hsh['ward']
|
33
|
+
u.agencyabbreviation = hsh['agencyabbreviation']
|
34
|
+
u.servicetypeocde = hsh['servicetypeocde']
|
35
|
+
|
36
|
+
|
37
|
+
u
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module DCGOV
|
2
|
+
class ServiceRequestField
|
3
|
+
include EasyClassMaker
|
4
|
+
#{"servicetype"=>[{"servicetype"=>"Abandoned Bicycles"}, {"servicecode"=>"S0021"},
|
5
|
+
#{"name"=>"ABDBIC-HOWLONG"}, {"prompt"=>"How long has the bicycle been abandoned?"},
|
6
|
+
# {"required"=>"Y"}, {"type"=>"TextBox "}, {"width"=>"200"}, {"itemlist"=>"\r"}]}
|
7
|
+
|
8
|
+
attributes :service_type,:service_code,:field_name,:field_label,:field_required,:field_type,:field_width,:item_list
|
9
|
+
|
10
|
+
# Creates a new user from a piece of xml
|
11
|
+
def self.new_from_hash(hsh)
|
12
|
+
u = new
|
13
|
+
u.service_type = hsh[0]['servicetype']
|
14
|
+
u.service_code = hsh[1]['servicecode']
|
15
|
+
u.field_name = hsh[2]['name']
|
16
|
+
u.field_label = hsh[3]['prompt']
|
17
|
+
u.field_required = hsh[4]['required']
|
18
|
+
u.field_type = hsh[5]['type']
|
19
|
+
u.field_width = hsh[6]['width']
|
20
|
+
u.item_list = hsh[7]['itemlist']
|
21
|
+
u
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module DCGOV
|
2
|
+
class ServiceType
|
3
|
+
include EasyClassMaker
|
4
|
+
attributes :service_type,:service_code
|
5
|
+
|
6
|
+
# Creates a new user from a piece of xml
|
7
|
+
def self.new_from_hash(hsh)
|
8
|
+
hash_to_proc = hsh.to_a
|
9
|
+
u = new
|
10
|
+
u.service_type = hash_to_proc[0]['servicetype']
|
11
|
+
u.service_code = hash_to_proc[1]['servicecode']
|
12
|
+
u
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
data/lib/dcgov/util.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module DCGOV
|
2
|
+
class Util
|
3
|
+
|
4
|
+
# just about all there is.
|
5
|
+
def self.pull_from_json(params)
|
6
|
+
|
7
|
+
#why am I wrapping the entire deal in a rescue block? Well, the API has no error handling at all
|
8
|
+
# so if you enter in something bad, it just craps on you.
|
9
|
+
begin
|
10
|
+
@resp
|
11
|
+
Net::HTTP.start('api.dc.gov') {|http|
|
12
|
+
req = Net::HTTP::Get.new(params)
|
13
|
+
response = http.request(req)
|
14
|
+
@resp = response.body
|
15
|
+
}
|
16
|
+
JSON.parse @resp
|
17
|
+
rescue
|
18
|
+
#so the caller can catch a "better" error than some JSON parsing or HTTP bs.
|
19
|
+
raise "An error occurred while attempting to grab and parse the results"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.post_to_json(params,url)
|
24
|
+
@resp
|
25
|
+
Net::HTTP.start('api.dc.gov') {|http|
|
26
|
+
req = Net::HTTP::Post.new(url)
|
27
|
+
req.set_form_data(params)
|
28
|
+
response = http.request(req)
|
29
|
+
@resp = response.body
|
30
|
+
}
|
31
|
+
JSON.parse @resp
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.fix_hash(hsh)
|
35
|
+
results = Hash.new
|
36
|
+
hsh.each { |i|
|
37
|
+
results.merge!(i)
|
38
|
+
}
|
39
|
+
return results
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe "DCGOV::GeoCoder" do
|
4
|
+
|
5
|
+
it "should be able to look up an address that exists" do
|
6
|
+
results = DCGOV::GeoCoder.get({:address=>"441 4th str, nw"})
|
7
|
+
results.length.should == 1
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be able to look up an address that doesn't exist" do
|
11
|
+
results = DCGOV::GeoCoder.get({:address=>"1dsggdsdgssdgdsgdsgdsgdgsW"})
|
12
|
+
results.length.should == 0
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should be able to look up an address that has multiple results" do
|
16
|
+
results = DCGOV::GeoCoder.get({:address=>"441 4th str"})
|
17
|
+
results.length.should == 2
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should be able to look up a latitude and a longitude" do
|
21
|
+
results = DCGOV::GeoCoder.get({:lat=>"38.89544591",:lon=>"-77.01565221"})
|
22
|
+
results[0].aid.should=="285552"
|
23
|
+
results.length.should > 0
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should be able to look up via a mar ID" do
|
27
|
+
aid = 285552
|
28
|
+
result = DCGOV::GeoCoder.get({:mar_id=>aid})
|
29
|
+
result.aid.to_i.should == aid
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return nil when a nonsensical mar is thrown" do
|
33
|
+
results = DCGOV::GeoCoder.get({:mar_id=>'adslkfhjdgsalkjgdlksdgjlgkds'})
|
34
|
+
results.should == nil
|
35
|
+
end
|
36
|
+
|
37
|
+
#stupid test. for fun.
|
38
|
+
it "should work" do
|
39
|
+
DCGOV::GeoCoder.foo.should == "bar"
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
2
|
+
|
3
|
+
describe "DCGOV::Open311" do
|
4
|
+
|
5
|
+
it "should return a list of service types" do
|
6
|
+
service_types = DCGOV::Open311.get_service_types()
|
7
|
+
service_types.length.should > 0
|
8
|
+
service_types[0].class.to_s.should == "DCGOV::ServiceType"
|
9
|
+
service_types[0].service_type.should =="Abandoned Bicycles"
|
10
|
+
service_types[0].service_code.should =="S0021"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return a list of fields for a service type" do
|
14
|
+
service_code="S0021"
|
15
|
+
request_fields = DCGOV::Open311.get_request_fields(service_code)
|
16
|
+
request_fields.length.should > 0
|
17
|
+
request_fields[0].service_type.should == "Abandoned Bicycles"
|
18
|
+
request_fields[0].field_name.should == "ABDBIC-HOWLONG"
|
19
|
+
request_fields[0].field_label.should == "How long has the bicycle been abandoned?"
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should return a request based on a service ID" do
|
24
|
+
request_id="123456"
|
25
|
+
request = DCGOV::Open311.get(request_id)
|
26
|
+
request.class.to_s.should == "Hash"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should convert a token into a service request id" do
|
30
|
+
token_id = "123456"
|
31
|
+
service_request_id = DCGOV::Open311.resolve_token(token_id)
|
32
|
+
service_request_id.should_not == nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should post a service request" do
|
36
|
+
values = Hash.new
|
37
|
+
token_id = DCGOV::Open311.submit(values)
|
38
|
+
token_id.should_not == nil
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
begin
|
2
|
+
require 'spec'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems'
|
5
|
+
gem 'rspec'
|
6
|
+
require 'spec'
|
7
|
+
end
|
8
|
+
|
9
|
+
dir = File.dirname(__FILE__)
|
10
|
+
|
11
|
+
$:.unshift(File.join(dir, '/../lib/'))
|
12
|
+
require dir + '/../lib/dcgov'
|
13
|
+
|
14
|
+
|
15
|
+
def stdout_for(&block)
|
16
|
+
# Inspired by http://www.ruby-forum.com/topic/58647
|
17
|
+
old_stdout = $stdout
|
18
|
+
$stdout = StringIO.new
|
19
|
+
yield
|
20
|
+
output = $stdout.string
|
21
|
+
$stdout = old_stdout
|
22
|
+
output
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: DCGOV
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Zvi Band
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-06 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json
|
17
|
+
type: :runtime
|
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 basic interface to the citywide API published by the District of Columbia
|
26
|
+
email: zvi@skeevisarts.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README
|
33
|
+
- LICENSE
|
34
|
+
files:
|
35
|
+
- LICENSE
|
36
|
+
- README
|
37
|
+
- Rakefile
|
38
|
+
- lib/dcgov
|
39
|
+
- lib/dcgov/address.rb
|
40
|
+
- lib/dcgov/easy_class_maker.rb
|
41
|
+
- lib/dcgov/geocoder.rb
|
42
|
+
- lib/dcgov/open311.rb
|
43
|
+
- lib/dcgov/service_request.rb
|
44
|
+
- lib/dcgov/service_request_field.rb
|
45
|
+
- lib/dcgov/service_type.rb
|
46
|
+
- lib/dcgov/util.rb
|
47
|
+
- lib/dcgov.rb
|
48
|
+
- spec/geocoder_spec.rb
|
49
|
+
- spec/open_311_spec.rb
|
50
|
+
- spec/spec_helper.rb
|
51
|
+
has_rdoc: true
|
52
|
+
homepage: http://skeevisarts.com
|
53
|
+
post_install_message:
|
54
|
+
rdoc_options: []
|
55
|
+
|
56
|
+
require_paths:
|
57
|
+
- lib
|
58
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: "0"
|
63
|
+
version:
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
version:
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.1
|
74
|
+
signing_key:
|
75
|
+
specification_version: 2
|
76
|
+
summary: A basic interface to the citywide API published by the District of Columbia
|
77
|
+
test_files: []
|
78
|
+
|