DCGOV 0.0.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 +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
|
+
|