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 CHANGED
@@ -1 +1 @@
1
- 0.3.2
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.3.2"
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-16}
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
- # API Key invalid
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
- instantiate_collection(result)
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
- instantiate_collection(result)
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
- instantiate_collection(result)
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
- instantiate_collection(result)
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
- instantiate_collection(result)
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
- instantiate_collection(result)
114
+ parse(result)
111
115
  end
112
116
  end
113
117
  end
@@ -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
- instantiate_record(response)
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/lower/bills/AB667/
22
- def self.find(state_abbrev, session, chamber, bill_id)
23
- response = get("/#{state_abbrev}/#{session}/#{chamber}/bills/#{bill_id}/")
24
- instantiate_record(response)
25
- end
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
- def self.search(query, options = {})
28
- response = get('/bills/', :query => {:q => query}.merge(options))
29
- instantiate_collection(response)
30
- end
28
+ def search(query, options = {})
29
+ response = get('/bills/', :query => {:q => query}.merge(options))
30
+ parse(response)
31
+ end
31
32
 
32
- def self.latest(updated_since, state_abbrev)
33
- response = get('/bills/latest/', :query => {:updated_since => updated_since, :state => state_abbrev})
34
- instantiate_collection(response)
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
- def self.find(legislator_id)
40
- response = get("/legislators/#{legislator_id}/")
41
- instantiate_record(response)
42
- end
41
+ class << self
42
+ def find(legislator_id)
43
+ response = get("/legislators/#{legislator_id}/")
44
+ parse(response)
45
+ end
43
46
 
44
- def self.search(options = {})
45
- response = get('/legislators/', :query => options)
46
- instantiate_collection(response)
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
- def self.find(committee_id)
52
- response = get("/committees/#{committee_id}/")
53
- instantiate_record(response)
54
- end
55
+ class << self
56
+ def find(committee_id)
57
+ response = get("/committees/#{committee_id}/")
58
+ parse(response)
59
+ end
55
60
 
56
- def self.search(options = {})
57
- response = get('/committees/', :query => options)
58
- instantiate_collection(response)
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
- instantiate_record(response)
83
+ parse(response)
79
84
  end
80
85
  end
81
86
  end
@@ -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 instantiate_record(record)
17
- raise ResourceNotFound, "Resource not found" unless !record.blank?
18
- new(record)
19
- end
20
-
21
- def instantiate_collection(collection)
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
- def parse(json)
26
- instantiate(json)
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
- when Hash
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(/^[_+]/,'').gsub(/^(\d)/, "n#{$1}").gsub(/\s/, '').camelize
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 > table.toc').previous_sibling.inner_html.scrub rescue ""
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)
@@ -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
- instantiate_record(response['address'])
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
- instantiate_record(response['webaddress'])
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
- instantiate_record(response['bio']['candidate'])
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
- instantiate(response['categories']['category'])
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'] && response['error']['errorMessage'] == 'No SIGs fit this criteria.'
44
+ raise(ResourceNotFound, response['error']['errorMessage']) if response['error']
45
45
 
46
- instantiate(response['sigs']['sig'])
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
- instantiate(response['sig'])
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'] && response['error']['errorMessage'] == 'No Ratings fit this criteria.'
59
+ raise(ResourceNotFound, response['error']['errorMessage']) if response['error']
60
60
 
61
- instantiate(response['candidateRating']['rating'])
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
- instantiate_record(response['bill'])
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
- instantiate_record(response['bills'])
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
- instantiate_record(response['bills'])
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
- instantiate_record(response['bills'])
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
- instantiate(response['categories']['category'])
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
- instantiate_record(response['committees'])
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
- instantiate_record(response['committee'])
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
@@ -7,7 +7,7 @@ module GovKit::OpenStates
7
7
 
8
8
  urls = [
9
9
  ['/ca/\?', 'state.response'],
10
- ['/ca/20092010/lower/bills/AB667/', 'bill.response'],
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
- - 3
8
- - 2
9
- version: 0.3.2
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-16 00:00:00 -07:00
19
+ date: 2010-09-29 00:00:00 -07:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency