govkit 0.3.2 → 0.4.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/VERSION +1 -1
- data/govkit.gemspec +2 -2
- data/lib/gov_kit/follow_the_money.rb +11 -7
- data/lib/gov_kit/open_states.rb +34 -29
- data/lib/gov_kit/resource.rb +29 -12
- data/lib/gov_kit/search_engines/wikipedia.rb +5 -1
- data/lib/gov_kit/vote_smart.rb +19 -19
- data/lib/gov_kit.rb +0 -10
- data/spec/open_states_spec.rb +1 -1
- metadata +4 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/govkit.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{govkit}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Participatory Politics Foundation", "Srinivas Aki", "Carl Tashian"]
|
12
|
-
s.date = %q{2010-09-
|
12
|
+
s.date = %q{2010-09-29}
|
13
13
|
s.description = %q{Govkit lets you quickly get encapsulated Ruby objects for common open government APIs. We're starting with Sunlight's Open States API and the Project Vote Smart API.}
|
14
14
|
s.email = %q{carl@ppolitics.org}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -9,13 +9,17 @@ module GovKit
|
|
9
9
|
|
10
10
|
e = doc.search("//error")
|
11
11
|
|
12
|
-
#
|
12
|
+
# Deal with whatever error comes back
|
13
13
|
if e.size > 0
|
14
14
|
raise case e.first.attributes['code']
|
15
15
|
when "100"
|
16
16
|
GovKit::NotAuthorized
|
17
17
|
when "300"
|
18
18
|
GovKit::InvalidRequest
|
19
|
+
when "200"
|
20
|
+
GovKit::ResourceNotFound
|
21
|
+
else
|
22
|
+
GovKit::InvalidRequest
|
19
23
|
end, e.first.attributes['text']
|
20
24
|
end
|
21
25
|
|
@@ -42,7 +46,7 @@ module GovKit
|
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
45
|
-
|
49
|
+
parse(result)
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
@@ -61,7 +65,7 @@ module GovKit
|
|
61
65
|
contribution.attributes.to_hash
|
62
66
|
end
|
63
67
|
end
|
64
|
-
|
68
|
+
parse(result)
|
65
69
|
end
|
66
70
|
|
67
71
|
def self.top(nimsp_id)
|
@@ -71,7 +75,7 @@ module GovKit
|
|
71
75
|
contribution.attributes.to_hash
|
72
76
|
end
|
73
77
|
|
74
|
-
|
78
|
+
parse(result)
|
75
79
|
end
|
76
80
|
end
|
77
81
|
|
@@ -83,7 +87,7 @@ module GovKit
|
|
83
87
|
contribution.attributes.to_hash
|
84
88
|
end
|
85
89
|
|
86
|
-
|
90
|
+
parse(result)
|
87
91
|
end
|
88
92
|
end
|
89
93
|
|
@@ -95,7 +99,7 @@ module GovKit
|
|
95
99
|
contribution.attributes.to_hash
|
96
100
|
end
|
97
101
|
|
98
|
-
|
102
|
+
parse(result)
|
99
103
|
end
|
100
104
|
end
|
101
105
|
|
@@ -107,7 +111,7 @@ module GovKit
|
|
107
111
|
contribution.attributes.to_hash
|
108
112
|
end
|
109
113
|
|
110
|
-
|
114
|
+
parse(result)
|
111
115
|
end
|
112
116
|
end
|
113
117
|
end
|
data/lib/gov_kit/open_states.rb
CHANGED
@@ -13,53 +13,58 @@ module GovKit
|
|
13
13
|
class State < OpenStatesResource
|
14
14
|
def self.find_by_abbreviation(abbreviation)
|
15
15
|
response = get("/metadata/#{abbreviation}/")
|
16
|
-
|
16
|
+
parse(response)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
class Bill < OpenStatesResource
|
21
|
-
# http://openstates.sunlightlabs.com/api/v1/ca/20092010/
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
# http://openstates.sunlightlabs.com/api/v1/bills/ca/20092010/AB667/
|
22
|
+
class << self
|
23
|
+
def find(state_abbrev, session, bill_id, chamber = '')
|
24
|
+
response = get("/bills/#{state_abbrev}/#{session}/#{chamber.blank? ? '' : chamber + '/'}#{bill_id}/")
|
25
|
+
parse(response)
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
def search(query, options = {})
|
29
|
+
response = get('/bills/', :query => {:q => query}.merge(options))
|
30
|
+
parse(response)
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
def latest(updated_since, state_abbrev)
|
34
|
+
response = get('/bills/latest/', :query => {:updated_since => updated_since, :state => state_abbrev})
|
35
|
+
parse(response)
|
36
|
+
end
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
40
|
class Legislator < OpenStatesResource
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
class << self
|
42
|
+
def find(legislator_id)
|
43
|
+
response = get("/legislators/#{legislator_id}/")
|
44
|
+
parse(response)
|
45
|
+
end
|
43
46
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
+
def search(options = {})
|
48
|
+
response = get('/legislators/', :query => options)
|
49
|
+
parse(response)
|
50
|
+
end
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
50
54
|
class Committee < OpenStatesResource
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
+
class << self
|
56
|
+
def find(committee_id)
|
57
|
+
response = get("/committees/#{committee_id}/")
|
58
|
+
parse(response)
|
59
|
+
end
|
55
60
|
|
56
|
-
|
57
|
-
|
58
|
-
|
61
|
+
def search(options = {})
|
62
|
+
response = get('/committees/', :query => options)
|
63
|
+
parse(response)
|
64
|
+
end
|
59
65
|
end
|
60
66
|
end
|
61
67
|
|
62
|
-
|
63
68
|
class Role < OpenStatesResource; end
|
64
69
|
|
65
70
|
class Sponsor < OpenStatesResource; end
|
@@ -75,7 +80,7 @@ module GovKit
|
|
75
80
|
class Vote < OpenStatesResource
|
76
81
|
def self.find(vote_id)
|
77
82
|
response = get("/votes/#{vote_id}/")
|
78
|
-
|
83
|
+
parse(response)
|
79
84
|
end
|
80
85
|
end
|
81
86
|
end
|
data/lib/gov_kit/resource.rb
CHANGED
@@ -9,35 +9,52 @@ module GovKit
|
|
9
9
|
def initialize(attributes = {})
|
10
10
|
@attributes = {}
|
11
11
|
@raw_response = attributes
|
12
|
+
|
12
13
|
unload(attributes)
|
13
14
|
end
|
14
15
|
|
15
16
|
class << self
|
16
|
-
def
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
collection.collect! { |record| instantiate_record(record) }
|
23
|
-
end
|
17
|
+
def parse(response)
|
18
|
+
# This method handles the basic responses we might get back from
|
19
|
+
# Net::HTTP. But if a service returns something other than a 404 when an object is not found,
|
20
|
+
# you'll need to handle that in the subclass.
|
21
|
+
|
22
|
+
raise ResourceNotFound, "Resource not found" unless !response.blank?
|
24
23
|
|
25
|
-
|
26
|
-
|
24
|
+
if response.class == HTTParty::Response
|
25
|
+
case response.response
|
26
|
+
when Net::HTTPNotFound
|
27
|
+
raise ResourceNotFound, "404 Not Found"
|
28
|
+
when Net::HTTPUnauthorized
|
29
|
+
raise NotAuthorized, "401 Not Authorized; have you set up your API key?"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
instantiate(response)
|
27
34
|
end
|
28
35
|
|
29
36
|
def instantiate(record)
|
30
37
|
case record
|
31
38
|
when Array
|
32
39
|
instantiate_collection(record)
|
33
|
-
|
40
|
+
else
|
34
41
|
instantiate_record(record)
|
35
42
|
end
|
36
43
|
end
|
44
|
+
|
45
|
+
def instantiate_record(record)
|
46
|
+
new(record)
|
47
|
+
end
|
48
|
+
|
49
|
+
def instantiate_collection(collection)
|
50
|
+
collection.collect! { |record| instantiate_record(record) }
|
51
|
+
end
|
52
|
+
|
37
53
|
end
|
38
54
|
|
39
55
|
def unload(attributes)
|
40
56
|
raise ArgumentError, "expected an attributes Hash, got #{attributes.inspect}" unless attributes.is_a?(Hash)
|
57
|
+
|
41
58
|
attributes.each do |key, value|
|
42
59
|
@attributes[key.to_s] =
|
43
60
|
case value
|
@@ -74,7 +91,7 @@ module GovKit
|
|
74
91
|
end
|
75
92
|
|
76
93
|
def find_or_create_resource_for(name)
|
77
|
-
resource_name = name.to_s.gsub(/^
|
94
|
+
resource_name = name.to_s.gsub(/^(\d)/, "n#{$1}").gsub(/\s/, '').camelize
|
78
95
|
if self.class.parents.size > 1
|
79
96
|
find_resource_in_modules(resource_name, self.class.parents)
|
80
97
|
else
|
@@ -10,7 +10,11 @@ module GovKit
|
|
10
10
|
response = get("/wiki/#{query}")
|
11
11
|
doc = Hpricot(Iconv.conv('utf-8//IGNORE', 'gb2312', response))
|
12
12
|
|
13
|
-
doc.at('#bodyContent >
|
13
|
+
bio = doc.at('#bodyContent > p:first').inner_html.scrub rescue ""
|
14
|
+
|
15
|
+
return "" if bio =~ /may refer to:/
|
16
|
+
|
17
|
+
bio
|
14
18
|
end
|
15
19
|
|
16
20
|
def self.make_request(host, path)
|
data/lib/gov_kit/vote_smart.rb
CHANGED
@@ -8,32 +8,32 @@ module GovKit
|
|
8
8
|
class Address < VoteSmartResource
|
9
9
|
def self.find(candidate_id)
|
10
10
|
response = get("/Address.getOffice", :query => {"candidateId" => candidate_id})
|
11
|
-
|
11
|
+
parse(response['address'])
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
class WebAddress < VoteSmartResource
|
16
16
|
def self.find(candidate_id)
|
17
17
|
response = get("/Address.getOfficeWebAddress", :query => {"candidateId" => candidate_id})
|
18
|
-
|
18
|
+
parse(response['webaddress'])
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
class Bio < VoteSmartResource
|
23
23
|
def self.find(candidate_id)
|
24
24
|
response = get("/CandidateBio.getBio", :query => {"candidateId" => candidate_id})
|
25
|
-
|
26
|
-
# Sometimes this returns nil if no one is found!
|
27
|
-
raise(ResourceNotFound, 'Could not find bio for candidate ' + candidate_id.to_s) if response.blank? || response['error']
|
28
25
|
|
29
|
-
|
26
|
+
# Sometimes VoteSmart returns nil if no one is found!
|
27
|
+
raise(ResourceNotFound, 'Could not find bio for candidate') if response.blank? || response['error']
|
28
|
+
|
29
|
+
parse(response['bio']['candidate'])
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
class Category < VoteSmartResource
|
34
34
|
def self.list(state_id)
|
35
35
|
response = get("/Rating.getCategories", :query => {"stateId" => state_id})
|
36
|
-
|
36
|
+
parse(response['categories']['category'])
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -41,14 +41,14 @@ module GovKit
|
|
41
41
|
def self.list(category_id, state_id)
|
42
42
|
response = get("/Rating.getSigList", :query => {"categoryId" => category_id, "stateId" => state_id})
|
43
43
|
|
44
|
-
raise(ResourceNotFound, response['error']['errorMessage']) if response['error']
|
44
|
+
raise(ResourceNotFound, response['error']['errorMessage']) if response['error']
|
45
45
|
|
46
|
-
|
46
|
+
parse(response['sigs']['sig'])
|
47
47
|
end
|
48
48
|
|
49
49
|
def self.find(sig_id)
|
50
50
|
response = get("/Rating.getSig", :query => {"sigId" => sig_id})
|
51
|
-
|
51
|
+
parse(response['sig'])
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -56,35 +56,35 @@ module GovKit
|
|
56
56
|
def self.find(candidate_id, sig_id)
|
57
57
|
response = get("/Rating.getCandidateRating", :query => {"candidateId" => candidate_id, "sigId" => sig_id})
|
58
58
|
|
59
|
-
raise(ResourceNotFound, response['error']['errorMessage']) if response['error']
|
59
|
+
raise(ResourceNotFound, response['error']['errorMessage']) if response['error']
|
60
60
|
|
61
|
-
|
61
|
+
parse(response['candidateRating']['rating'])
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
65
|
class Bill < VoteSmartResource
|
66
66
|
def self.find(bill_id)
|
67
67
|
response = get('/Votes.getBill', :query => {'billId' => bill_id})
|
68
|
-
|
68
|
+
parse(response['bill'])
|
69
69
|
end
|
70
70
|
|
71
71
|
def self.find_by_year_and_state(year, state_abbrev)
|
72
72
|
response = get('/Votes.getBillsByYearState', :query => {'year' => year, 'stateId' => state_abbrev})
|
73
73
|
raise(ResourceNotFound, response['error']['errorMessage']) if response['error'] && response['error']['errorMessage'] == 'No bills for this state and year.'
|
74
74
|
|
75
|
-
|
75
|
+
parse(response['bills'])
|
76
76
|
end
|
77
77
|
|
78
78
|
def self.find_recent_by_state(state_abbrev)
|
79
79
|
response = get('/Votes.getBillsByStateRecent', :query => {'stateId' => state_abbrev})
|
80
|
-
|
80
|
+
parse(response['bills'])
|
81
81
|
end
|
82
82
|
|
83
83
|
def self.find_by_category_and_year_and_state(category_id, year, state_abbrev = nil)
|
84
84
|
response = get('/Votes.getBillsByCategoryYearState', :query => {'stateId' => state_abbrev, 'year' => year, 'categoryId' => category_id})
|
85
85
|
raise(ResourceNotFound, response['error']['errorMessage']) if response['error'] && response['error']['errorMessage'] == 'No bills for this state, category, and year.'
|
86
86
|
|
87
|
-
|
87
|
+
parse(response['bills'])
|
88
88
|
end
|
89
89
|
|
90
90
|
def self.find_by_category_and_year(category_id, year)
|
@@ -95,7 +95,7 @@ module GovKit
|
|
95
95
|
class BillCategory < VoteSmartResource
|
96
96
|
def self.find(year, state_abbrev)
|
97
97
|
response = get("/Votes.getCategories", :query => {'year' => year, 'stateId' => state_abbrev})
|
98
|
-
|
98
|
+
parse(response['categories']['category'])
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
@@ -106,13 +106,13 @@ module GovKit
|
|
106
106
|
# This method maps to Committee.getCommitteesByTypeState()
|
107
107
|
def self.find_by_type_and_state(type_id, state_abbrev)
|
108
108
|
response = get('/Committee.getCommitteesByTypeState', :query => {'typeId' => type_id, 'stateId' => state_abbrev})
|
109
|
-
|
109
|
+
parse(response['committees'])
|
110
110
|
end
|
111
111
|
|
112
112
|
# Find a committee by VoteSmart committeeId. Maps to Committee.getCommittee()
|
113
113
|
def self.find(committee_id)
|
114
114
|
response = get('/Committee.getCommittee', :query => {'committeeId' => committee_id})
|
115
|
-
|
115
|
+
parse(response['committee'])
|
116
116
|
end
|
117
117
|
end
|
118
118
|
end
|
data/lib/gov_kit.rb
CHANGED
@@ -21,16 +21,6 @@ module GovKit
|
|
21
21
|
end
|
22
22
|
|
23
23
|
class GovKitError < StandardError
|
24
|
-
attr_reader :response
|
25
|
-
|
26
|
-
def initialize(response, message = nil)
|
27
|
-
@response = response
|
28
|
-
@message = message
|
29
|
-
end
|
30
|
-
|
31
|
-
def to_s
|
32
|
-
"Failed with #{response.code if response.respond_to?(:code)} #{response.message if response.respond_to?(:message)}"
|
33
|
-
end
|
34
24
|
end
|
35
25
|
|
36
26
|
class NotAuthorized < GovKitError; end
|
data/spec/open_states_spec.rb
CHANGED
@@ -7,7 +7,7 @@ module GovKit::OpenStates
|
|
7
7
|
|
8
8
|
urls = [
|
9
9
|
['/ca/\?', 'state.response'],
|
10
|
-
['/ca/20092010/
|
10
|
+
['/bills/ca/20092010/AB667/', 'bill.response'],
|
11
11
|
['/bills/search/\?', 'bill_query.response'],
|
12
12
|
['/bills/latest/\?', 'bill_query.response'],
|
13
13
|
['/legislators/2462/\?', 'legislator.response'],
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 4
|
8
|
+
- 0
|
9
|
+
version: 0.4.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Participatory Politics Foundation
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-09-
|
19
|
+
date: 2010-09-29 00:00:00 -07:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|