govkit 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +2 -2
- data/Rakefile +4 -5
- data/VERSION +1 -1
- data/generators/govkit/templates/govkit.rb +4 -4
- data/govkit.gemspec +22 -7
- data/init.rb +4 -0
- data/lib/gov_kit/acts_as_citeable.rb +1 -1
- data/lib/gov_kit/configuration.rb +4 -4
- data/lib/gov_kit/follow_the_money.rb +30 -16
- data/lib/gov_kit/{fifty_states.rb → open_states.rb} +25 -13
- data/lib/gov_kit/railtie.rb +20 -0
- data/lib/gov_kit/resource.rb +17 -37
- data/lib/gov_kit/search_engines/google_news.rb +4 -4
- data/lib/gov_kit/search_engines/wikipedia.rb +21 -0
- data/lib/gov_kit/search_engines.rb +1 -0
- data/lib/gov_kit/vote_smart.rb +68 -4
- data/lib/gov_kit.rb +25 -24
- data/spec/fixtures/follow_the_money/business-page0.response +28 -0
- data/spec/fixtures/follow_the_money/business-page1.response +12 -0
- data/spec/fixtures/follow_the_money/contribution.response +12 -0
- data/spec/fixtures/follow_the_money/unauthorized.response +8 -0
- data/spec/fixtures/open_states/401.response +6 -0
- data/spec/fixtures/open_states/410.response +6 -0
- data/spec/fixtures/open_states/bill.response +240 -0
- data/spec/fixtures/open_states/bill_query.response +1990 -0
- data/spec/fixtures/open_states/legislator.response +34 -0
- data/spec/fixtures/open_states/legislator_query.response +144 -0
- data/spec/fixtures/open_states/state.response +60 -0
- data/spec/follow_the_money_spec.rb +57 -0
- data/spec/open_states_spec.rb +131 -0
- data/spec/spec_helper.rb +13 -0
- metadata +23 -14
- data/rails/init.rb +0 -3
- data/spec/fifty_states_spec.rb +0 -90
data/README.markdown
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
Govkit is a Ruby gem that provides simple access to open government APIs around the web, including:
|
4
4
|
|
5
5
|
* [OpenCongress](http://www.opencongress.org/api), which has an API for federal bills, votes, people, and news and blog coverage
|
6
|
-
* [The
|
6
|
+
* [The Open States project](http://fiftystates-dev.sunlightlabs.com/), which has a RESTful API for accessing data about state legislators, bills, votes, etc.
|
7
7
|
* [Project Vote Smart](http://www.votesmart.org/services_api.php), which has an API with congressional addresses, etc.
|
8
8
|
* [Follow The Money](http://www.followthemoney.org/), whose API reveals campaign contribution data for state officials.
|
9
9
|
|
@@ -21,7 +21,7 @@ Run <code>./script/generate govkit</code> to copy a config file into <code>confi
|
|
21
21
|
|
22
22
|
# Examples
|
23
23
|
|
24
|
-
>> Govkit::
|
24
|
+
>> Govkit::OpenStates::State.find_by_abbreviation('CA')
|
25
25
|
>> Govkit::VoteSmart::Address.find(votesmart_candidate_id)
|
26
26
|
>> GovKit::OpenCongress::Bill.find(:number => 5479, :type => 'h', :congress => '111')
|
27
27
|
|
data/Rakefile
CHANGED
@@ -2,13 +2,12 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'rake/rdoctask'
|
4
4
|
|
5
|
-
|
6
5
|
begin
|
7
|
-
require '
|
6
|
+
require 'rspec/core/rake_task'
|
8
7
|
rescue LoadError
|
9
8
|
begin
|
10
|
-
gem 'rspec-rails', '>=
|
11
|
-
require '
|
9
|
+
gem 'rspec-rails', '>= 2.0.0'
|
10
|
+
require 'rspec/core/rake_task'
|
12
11
|
rescue LoadError
|
13
12
|
puts "[govkit:] RSpec - or one of it's dependencies - is not available. Install it with: sudo gem install rspec-rails"
|
14
13
|
end
|
@@ -19,7 +18,7 @@ begin
|
|
19
18
|
Jeweler::Tasks.new do |gem|
|
20
19
|
gem.name = "govkit"
|
21
20
|
gem.summary = %Q{Simple access to open government APIs around the web}
|
22
|
-
gem.description = %Q{Govkit lets you quickly get encapsulated Ruby objects for common open government APIs. We're starting with Sunlight's
|
21
|
+
gem.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.}
|
23
22
|
gem.email = "carl@ppolitics.org"
|
24
23
|
gem.homepage = "http://github.com/opengovernment/govkit"
|
25
24
|
gem.authors = ["Participatory Politics Foundation", "Srinivas Aki", "Carl Tashian"]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -1,17 +1,17 @@
|
|
1
1
|
if defined? GovKit
|
2
2
|
GovKit.configure do |config|
|
3
|
-
# Get an API key for Sunlight's
|
3
|
+
# Get an API key for Sunlight's Open States project here:
|
4
4
|
# http://services.sunlightlabs.com/accounts/register/
|
5
|
-
config.
|
5
|
+
config.openstates_apikey = 'YOUR_OPENSTATES_API_KEY'
|
6
6
|
|
7
7
|
##API key for Votesmart
|
8
8
|
# http://votesmart.org/services_api.php
|
9
9
|
config.votesmart_apikey = 'YOUR_VOTESMART_API_KEY'
|
10
|
-
|
10
|
+
|
11
11
|
# API key for NIMSP. Request one here:
|
12
12
|
# http://www.followthemoney.org/membership/settings.phtml
|
13
13
|
config.ftm_apikey = 'YOUR_FTM_API_KEY'
|
14
|
-
|
14
|
+
|
15
15
|
# Api key for OpenCongress
|
16
16
|
# http://www.opencongress.org/api
|
17
17
|
config.opencongress_apikey = 'YOUR_OPENCONGRESS_API_KEY'
|
data/govkit.gemspec
CHANGED
@@ -5,12 +5,12 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{govkit}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.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-
|
13
|
-
s.description = %q{Govkit lets you quickly get encapsulated Ruby objects for common open government APIs. We're starting with Sunlight's
|
12
|
+
s.date = %q{2010-08-31}
|
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 = [
|
16
16
|
"LICENSE",
|
@@ -27,10 +27,10 @@ Gem::Specification.new do |s|
|
|
27
27
|
"generators/govkit/govkit_generator.rb",
|
28
28
|
"generators/govkit/templates/govkit.rb",
|
29
29
|
"govkit.gemspec",
|
30
|
+
"init.rb",
|
30
31
|
"lib/gov_kit.rb",
|
31
32
|
"lib/gov_kit/acts_as_citeable.rb",
|
32
33
|
"lib/gov_kit/configuration.rb",
|
33
|
-
"lib/gov_kit/fifty_states.rb",
|
34
34
|
"lib/gov_kit/follow_the_money.rb",
|
35
35
|
"lib/gov_kit/open_congress.rb",
|
36
36
|
"lib/gov_kit/open_congress/bill.rb",
|
@@ -41,15 +41,29 @@ Gem::Specification.new do |s|
|
|
41
41
|
"lib/gov_kit/open_congress/roll_call.rb",
|
42
42
|
"lib/gov_kit/open_congress/roll_call_comparison.rb",
|
43
43
|
"lib/gov_kit/open_congress/voting_comparison.rb",
|
44
|
+
"lib/gov_kit/open_states.rb",
|
45
|
+
"lib/gov_kit/railtie.rb",
|
44
46
|
"lib/gov_kit/resource.rb",
|
45
47
|
"lib/gov_kit/search_engines.rb",
|
46
48
|
"lib/gov_kit/search_engines/google_blog.rb",
|
47
49
|
"lib/gov_kit/search_engines/google_news.rb",
|
48
50
|
"lib/gov_kit/search_engines/technorati.rb",
|
51
|
+
"lib/gov_kit/search_engines/wikipedia.rb",
|
49
52
|
"lib/gov_kit/vote_smart.rb",
|
50
53
|
"lib/govkit.rb",
|
51
|
-
"
|
52
|
-
"spec/
|
54
|
+
"spec/fixtures/follow_the_money/business-page0.response",
|
55
|
+
"spec/fixtures/follow_the_money/business-page1.response",
|
56
|
+
"spec/fixtures/follow_the_money/contribution.response",
|
57
|
+
"spec/fixtures/follow_the_money/unauthorized.response",
|
58
|
+
"spec/fixtures/open_states/401.response",
|
59
|
+
"spec/fixtures/open_states/410.response",
|
60
|
+
"spec/fixtures/open_states/bill.response",
|
61
|
+
"spec/fixtures/open_states/bill_query.response",
|
62
|
+
"spec/fixtures/open_states/legislator.response",
|
63
|
+
"spec/fixtures/open_states/legislator_query.response",
|
64
|
+
"spec/fixtures/open_states/state.response",
|
65
|
+
"spec/follow_the_money_spec.rb",
|
66
|
+
"spec/open_states_spec.rb",
|
53
67
|
"spec/spec.opts",
|
54
68
|
"spec/spec_helper.rb"
|
55
69
|
]
|
@@ -59,7 +73,8 @@ Gem::Specification.new do |s|
|
|
59
73
|
s.rubygems_version = %q{1.3.7}
|
60
74
|
s.summary = %q{Simple access to open government APIs around the web}
|
61
75
|
s.test_files = [
|
62
|
-
"spec/
|
76
|
+
"spec/follow_the_money_spec.rb",
|
77
|
+
"spec/open_states_spec.rb",
|
63
78
|
"spec/spec_helper.rb"
|
64
79
|
]
|
65
80
|
|
data/init.rb
ADDED
@@ -1,13 +1,13 @@
|
|
1
1
|
module GovKit
|
2
2
|
class Configuration
|
3
|
-
attr_accessor :
|
3
|
+
attr_accessor :openstates_apikey, :openstates_base_url
|
4
4
|
attr_accessor :votesmart_apikey, :votesmart_base_url
|
5
5
|
attr_accessor :ftm_apikey, :ftm_base_url
|
6
6
|
attr_accessor :opencongress_apikey, :opencongress_base_url
|
7
7
|
|
8
8
|
def initialize
|
9
|
-
@
|
10
|
-
@
|
9
|
+
@openstates_apikey = @votesmart_apikey = @ftm_apikey = ''
|
10
|
+
@openstates_base_url = 'fiftystates-dev.sunlightlabs.com/api'
|
11
11
|
@votesmart_base_url = 'api.votesmart.org/'
|
12
12
|
@ftm_base_url = 'api.followthemoney.org/'
|
13
13
|
@opencongress_base_url = 'www.opencongress.org/'
|
@@ -22,7 +22,7 @@ module GovKit
|
|
22
22
|
#
|
23
23
|
# @example
|
24
24
|
# GovKit.configure do |config|
|
25
|
-
# config.
|
25
|
+
# config.openstates_apikey = ''
|
26
26
|
# end
|
27
27
|
def self.configure
|
28
28
|
self.configuration ||= Configuration.new
|
@@ -2,6 +2,25 @@ module GovKit
|
|
2
2
|
class FollowTheMoneyResource < Resource
|
3
3
|
default_params :key => GovKit::configuration.ftm_apikey
|
4
4
|
base_uri GovKit::configuration.ftm_base_url
|
5
|
+
|
6
|
+
def self.get_xml(path, options)
|
7
|
+
response = get(path, options)
|
8
|
+
doc = Hpricot::XML(response)
|
9
|
+
|
10
|
+
e = doc.search("//error")
|
11
|
+
|
12
|
+
# API Key invalid
|
13
|
+
if e.size > 0
|
14
|
+
raise case e.first.attributes['code']
|
15
|
+
when "100"
|
16
|
+
GovKit::NotAuthorized
|
17
|
+
when "300"
|
18
|
+
GovKit::InvalidRequest
|
19
|
+
end, e.first.attributes['text']
|
20
|
+
end
|
21
|
+
|
22
|
+
doc
|
23
|
+
end
|
5
24
|
end
|
6
25
|
|
7
26
|
module FollowTheMoney
|
@@ -9,12 +28,10 @@ module GovKit
|
|
9
28
|
def self.list
|
10
29
|
next_page, result, page_num = "yes", [], 0
|
11
30
|
|
12
|
-
until next_page
|
13
|
-
puts "Getting batch number #{page_num}"
|
14
|
-
|
15
|
-
response = get("/base_level.industries.list.php", :query => {:page => page_num})
|
31
|
+
until next_page != "yes"
|
32
|
+
# puts "Getting batch number #{page_num}"
|
16
33
|
|
17
|
-
doc =
|
34
|
+
doc = get_xml("/base_level.industries.list.php", :query => {:page => page_num})
|
18
35
|
|
19
36
|
next_page = doc.search("/").first.attributes['next_page']
|
20
37
|
|
@@ -33,9 +50,8 @@ module GovKit
|
|
33
50
|
def self.find(nimsp_id)
|
34
51
|
next_page, result, page_num = "yes", [], 0
|
35
52
|
|
36
|
-
until next_page
|
37
|
-
|
38
|
-
doc = Hpricot::XML(response)
|
53
|
+
until next_page != "yes"
|
54
|
+
doc = get_xml("/candidates.contributions.php", :query => {"imsp_candidate_id" => nimsp_id, :page => page_num})
|
39
55
|
|
40
56
|
next_page = doc.search("/").first.attributes['next_page']
|
41
57
|
|
@@ -49,8 +65,8 @@ module GovKit
|
|
49
65
|
end
|
50
66
|
|
51
67
|
def self.top(nimsp_id)
|
52
|
-
|
53
|
-
|
68
|
+
doc = get_xml("/candidates.top_contributor.php", :query => {"imsp_candidate_id" => nimsp_id})
|
69
|
+
|
54
70
|
result = doc.search('//top_contributor').collect do |contribution|
|
55
71
|
contribution.attributes.to_hash
|
56
72
|
end
|
@@ -61,8 +77,7 @@ module GovKit
|
|
61
77
|
|
62
78
|
class IndustryContribution < Contribution
|
63
79
|
def self.find(nimsp_id)
|
64
|
-
|
65
|
-
doc = Hpricot::XML(response)
|
80
|
+
doc = get_xml("/candidates.industries.php", :query => {"imsp_candidate_id" => nimsp_id})
|
66
81
|
|
67
82
|
result = doc.search('//candidate_industry').collect do |contribution|
|
68
83
|
contribution.attributes.to_hash
|
@@ -74,8 +89,7 @@ module GovKit
|
|
74
89
|
|
75
90
|
class SectorContribution < Contribution
|
76
91
|
def self.find(nimsp_id)
|
77
|
-
|
78
|
-
doc = Hpricot::XML(response)
|
92
|
+
doc = get_xml("/candidates.sectors.php", :query => {"imsp_candidate_id" => nimsp_id})
|
79
93
|
|
80
94
|
result = doc.search('//candidate_sector').collect do |contribution|
|
81
95
|
contribution.attributes.to_hash
|
@@ -87,8 +101,8 @@ module GovKit
|
|
87
101
|
|
88
102
|
class BusinessContribution < Contribution
|
89
103
|
def self.find(nimsp_id)
|
90
|
-
|
91
|
-
|
104
|
+
doc = get_xml("/candidates.businesses.php", :query => {"imsp_candidate_id" => nimsp_id})
|
105
|
+
|
92
106
|
result = doc.search('//candidate_business').collect do |contribution|
|
93
107
|
contribution.attributes.to_hash
|
94
108
|
end
|
@@ -1,23 +1,23 @@
|
|
1
1
|
module GovKit
|
2
|
-
class
|
3
|
-
default_params :output => 'json', :apikey => GovKit::configuration.
|
4
|
-
base_uri GovKit::configuration.
|
2
|
+
class OpenStatesResource < Resource
|
3
|
+
default_params :output => 'json', :apikey => GovKit::configuration.openstates_apikey
|
4
|
+
base_uri GovKit::configuration.openstates_base_url
|
5
5
|
end
|
6
6
|
|
7
|
-
module
|
7
|
+
module OpenStates
|
8
8
|
ROLE_MEMBER = "member"
|
9
9
|
ROLE_COMMITTEE_MEMBER = "committee member"
|
10
10
|
CHAMBER_UPPER = "upper"
|
11
11
|
CHAMBER_LOWER = "lower"
|
12
12
|
|
13
|
-
class State <
|
13
|
+
class State < OpenStatesResource
|
14
14
|
def self.find_by_abbreviation(abbreviation)
|
15
|
-
response = get("/#{abbreviation}")
|
15
|
+
response = get("/#{abbreviation}/")
|
16
16
|
instantiate_record(response)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
class Bill <
|
20
|
+
class Bill < OpenStatesResource
|
21
21
|
# http://fiftystates-dev.sunlightlabs.com/api/ca/20092010/lower/bills/AB667/
|
22
22
|
def self.find(state_abbrev, session, chamber, bill_id)
|
23
23
|
response = get("/#{state_abbrev}/#{session}/#{chamber}/bills/#{bill_id}/")
|
@@ -25,7 +25,7 @@ module GovKit
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def self.search(query, options = {})
|
28
|
-
response = get('/bills/search', :query => {:q => query}.merge(options))
|
28
|
+
response = get('/bills/search/', :query => {:q => query}.merge(options))
|
29
29
|
instantiate_collection(response)
|
30
30
|
end
|
31
31
|
|
@@ -35,21 +35,33 @@ module GovKit
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
class Legislator <
|
38
|
+
class Legislator < OpenStatesResource
|
39
39
|
def self.find(legislator_id)
|
40
|
-
response = get("/legislators/#{legislator_id}")
|
40
|
+
response = get("/legislators/#{legislator_id}/")
|
41
41
|
instantiate_record(response)
|
42
42
|
end
|
43
43
|
|
44
44
|
def self.search(options = {})
|
45
|
-
response = get('/legislators/search', :query => options)
|
45
|
+
response = get('/legislators/search/', :query => options)
|
46
46
|
instantiate_collection(response)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
class
|
50
|
+
class Role < OpenStatesResource; end
|
51
|
+
|
52
|
+
class Sponsor < OpenStatesResource; end
|
53
|
+
|
54
|
+
class Version < OpenStatesResource; end
|
55
|
+
|
56
|
+
class Source < OpenStatesResource; end
|
57
|
+
|
58
|
+
class Address < OpenStatesResource; end
|
59
|
+
|
60
|
+
class Action < OpenStatesResource; end
|
61
|
+
|
62
|
+
class Vote < OpenStatesResource
|
51
63
|
def self.find(vote_id)
|
52
|
-
response = get("/votes/#{vote_id}")
|
64
|
+
response = get("/votes/#{vote_id}/")
|
53
65
|
instantiate_record(response)
|
54
66
|
end
|
55
67
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'govkit'
|
2
|
+
|
3
|
+
module GovKit
|
4
|
+
if defined? Rails::Railtie
|
5
|
+
require 'rails'
|
6
|
+
class Railtie < Rails::Railtie
|
7
|
+
initializer 'govkit.insert_into_active_record' do
|
8
|
+
ActiveSupport.on_load :active_record do
|
9
|
+
GovKit::Railtie.insert
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Railtie
|
16
|
+
def self.insert
|
17
|
+
ActiveRecord::Base.send(:include, GovKit::ActsAsCiteable)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/gov_kit/resource.rb
CHANGED
@@ -1,29 +1,4 @@
|
|
1
1
|
module GovKit
|
2
|
-
class GovKitError < StandardError
|
3
|
-
attr_reader :response
|
4
|
-
|
5
|
-
def initialize(response, message = nil)
|
6
|
-
@response = response
|
7
|
-
@message = message
|
8
|
-
end
|
9
|
-
|
10
|
-
def to_s
|
11
|
-
"Failed with #{response.code} #{response.message if response.respond_to?(:message)}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class NotauthorizedError < GovKitError;
|
16
|
-
end
|
17
|
-
|
18
|
-
class InvalidRequestError < GovKitError;
|
19
|
-
end
|
20
|
-
|
21
|
-
class NotFoundError < GovKitError;
|
22
|
-
end
|
23
|
-
|
24
|
-
class NameError < GovKitError;
|
25
|
-
end
|
26
|
-
|
27
2
|
class Resource
|
28
3
|
include HTTParty
|
29
4
|
format :json
|
@@ -37,6 +12,7 @@ module GovKit
|
|
37
12
|
|
38
13
|
class << self
|
39
14
|
def instantiate_record(record)
|
15
|
+
raise ResourceNotFound, "Resource not found" unless !record.blank?
|
40
16
|
new(record)
|
41
17
|
end
|
42
18
|
|
@@ -45,7 +21,16 @@ module GovKit
|
|
45
21
|
end
|
46
22
|
|
47
23
|
def parse(json)
|
48
|
-
|
24
|
+
instantiate(json)
|
25
|
+
end
|
26
|
+
|
27
|
+
def instantiate(record)
|
28
|
+
case record
|
29
|
+
when Array
|
30
|
+
instantiate_collection(record)
|
31
|
+
when Hash
|
32
|
+
instantiate_record(record)
|
33
|
+
end
|
49
34
|
end
|
50
35
|
end
|
51
36
|
|
@@ -78,12 +63,8 @@ module GovKit
|
|
78
63
|
find_or_create_resource_for(name.to_s.singularize)
|
79
64
|
end
|
80
65
|
|
81
|
-
def find_resource_in_modules(resource_name,
|
82
|
-
|
83
|
-
namespaces = module_names[0, module_names.size-1].map do |module_name|
|
84
|
-
receiver = receiver.const_get(module_name)
|
85
|
-
end
|
86
|
-
if namespace = namespaces.reverse.detect { |ns| ns.const_defined?(resource_name) }
|
66
|
+
def find_resource_in_modules(resource_name, ancestors)
|
67
|
+
if namespace = ancestors.detect { |a| a.constants.include?(resource_name.to_sym) }
|
87
68
|
return namespace.const_get(resource_name)
|
88
69
|
else
|
89
70
|
raise NameError, "Namespace for #{namespace} not found"
|
@@ -91,10 +72,9 @@ module GovKit
|
|
91
72
|
end
|
92
73
|
|
93
74
|
def find_or_create_resource_for(name)
|
94
|
-
resource_name = name.to_s.camelize
|
95
|
-
|
96
|
-
|
97
|
-
find_resource_in_modules(resource_name, ancestors)
|
75
|
+
resource_name = name.to_s.gsub(/^_/,'').gsub(/^(\d)/, "n#{$1}").gsub(/\s/, '').camelize
|
76
|
+
if self.class.parents.size > 1
|
77
|
+
find_resource_in_modules(resource_name, self.class.parents)
|
98
78
|
else
|
99
79
|
self.class.const_get(resource_name)
|
100
80
|
end
|
@@ -114,7 +94,7 @@ module GovKit
|
|
114
94
|
when "="
|
115
95
|
attributes[method_name.first(-1)] = arguments.first
|
116
96
|
when "?"
|
117
|
-
attributes[method_name.first(-1)]
|
97
|
+
!attributes[method_name.first(-1)].blank?
|
118
98
|
when "]"
|
119
99
|
attributes[arguments.first.to_s]
|
120
100
|
else
|
@@ -18,11 +18,11 @@ module GovKit
|
|
18
18
|
stories.each do |story|
|
19
19
|
citation = GovKit::Citation.new
|
20
20
|
|
21
|
-
citation.title = story.at("h2.title a").inner_text.html_safe
|
21
|
+
citation.title = story.at("h2.title a").inner_text.html_safe
|
22
22
|
citation.url = story.at("h2.title a").attributes["href"]
|
23
|
-
citation.date = story.at("div.sub-title > span.date").inner_html.html_safe
|
24
|
-
citation.source = story.at("div.sub-title > span.source").inner_html.html_safe
|
25
|
-
citation.excerpt = story.at("div.body > div.snippet").inner_html.html_safe
|
23
|
+
citation.date = story.at("div.sub-title > span.date").inner_html.html_safe
|
24
|
+
citation.source = story.at("div.sub-title > span.source").inner_html.html_safe
|
25
|
+
citation.excerpt = story.at("div.body > div.snippet").inner_html.html_safe
|
26
26
|
|
27
27
|
citations << citation
|
28
28
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module GovKit
|
2
|
+
module SearchEngines
|
3
|
+
class Wikipedia
|
4
|
+
include HTTParty
|
5
|
+
default_params :format => 'xml'
|
6
|
+
base_uri "en.wikipedia.org"
|
7
|
+
headers 'User-Agent' => 'GovKit +http://opengovernment.org'
|
8
|
+
|
9
|
+
def self.search(query, options={})
|
10
|
+
response = get("/wiki/#{query}")
|
11
|
+
doc = Hpricot(Iconv.conv('utf-8//IGNORE', 'gb2312', response))
|
12
|
+
|
13
|
+
doc.at('#bodyContent > table.toc').previous_sibling.inner_html.scrub rescue ""
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.make_request(host, path)
|
17
|
+
response = Net::HTTP.get(host, path)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -2,4 +2,5 @@ module GovKit::SearchEngines
|
|
2
2
|
autoload :GoogleNews, 'gov_kit/search_engines/google_news'
|
3
3
|
autoload :GoogleBlog, 'gov_kit/search_engines/google_blog'
|
4
4
|
autoload :Technorati, 'gov_kit/search_engines/technorati'
|
5
|
+
autoload :Wikipedia, 'gov_kit/search_engines/wikipedia'
|
5
6
|
end
|
data/lib/gov_kit/vote_smart.rb
CHANGED
@@ -19,16 +19,80 @@ module GovKit
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
class Bio < VoteSmartResource
|
23
|
+
def self.find(candidate_id)
|
24
|
+
response = get("/CandidateBio.getBio", :query => {"candidateId" => candidate_id})
|
25
|
+
instantiate_record(response['bio']['candidate'])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Category < VoteSmartResource
|
30
|
+
def self.list(state_id)
|
31
|
+
response = get("/Rating.getCategories", :query => {"stateId" => state_id})
|
32
|
+
instantiate(response['categories']['category'])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class SIG < VoteSmartResource
|
37
|
+
def self.list(category_id, state_id)
|
38
|
+
response = get("/Rating.getSigList", :query => {"categoryId" => category_id, "stateId" => state_id})
|
39
|
+
|
40
|
+
raise(ResourceNotFound, response['error']['errorMessage']) if response['error'] && response['error']['errorMessage'] == 'No SIGs fit this criteria.'
|
41
|
+
|
42
|
+
instantiate(response['sigs']['sig'])
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.find(sig_id)
|
46
|
+
response = get("/Rating.getSig", :query => {"sigId" => sig_id})
|
47
|
+
instantiate(response['sig'])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Rating < VoteSmartResource
|
52
|
+
def self.find(candidate_id, sig_id)
|
53
|
+
response = get("/Rating.getCandidateRating", :query => {"candidateId" => candidate_id, "sigId" => sig_id})
|
54
|
+
|
55
|
+
raise(ResourceNotFound, response['error']['errorMessage']) if response['error'] && response['error']['errorMessage'] == 'No Ratings fit this criteria.'
|
56
|
+
|
57
|
+
instantiate(response['candidateRating']['rating'])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
22
61
|
class Bill < VoteSmartResource
|
23
62
|
def self.find(bill_id)
|
24
|
-
response = get(
|
63
|
+
response = get('/Votes.getBill', :query => {'billId' => bill_id})
|
25
64
|
instantiate_record(response['bill'])
|
26
65
|
end
|
27
66
|
|
28
67
|
def self.find_by_year_and_state(year, state_abbrev)
|
29
|
-
response = get(
|
68
|
+
response = get('/Votes.getBillsByYearState', :query => {'year' => year, 'stateId' => state_abbrev})
|
69
|
+
raise(ResourceNotFound, response['error']['errorMessage']) if response['error'] && response['error']['errorMessage'] == 'No bills for this state and year.'
|
70
|
+
|
71
|
+
instantiate_record(response['bills'])
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.find_recent_by_state(state_abbrev)
|
75
|
+
response = get('/Votes.getBillsByStateRecent', :query => {'stateId' => state_abbrev})
|
30
76
|
instantiate_record(response['bills'])
|
31
77
|
end
|
78
|
+
|
79
|
+
def self.find_by_category_and_year_and_state(category_id, year, state_abbrev = nil)
|
80
|
+
response = get('/Votes.getBillsByCategoryYearState', :query => {'stateId' => state_abbrev, 'year' => year, 'categoryId' => category_id})
|
81
|
+
raise(ResourceNotFound, response['error']['errorMessage']) if response['error'] && response['error']['errorMessage'] == 'No bills for this state, category, and year.'
|
82
|
+
|
83
|
+
instantiate_record(response['bills'])
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.find_by_category_and_year(category_id, year)
|
87
|
+
find_by_category_and_year_and_state(category_id, year)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class BillCategory < VoteSmartResource
|
92
|
+
def self.find(year, state_abbrev)
|
93
|
+
response = get("/Votes.getCategories", :query => {'year' => year, 'stateId' => state_abbrev})
|
94
|
+
instantiate(response['categories']['category'])
|
95
|
+
end
|
32
96
|
end
|
33
97
|
|
34
98
|
# See http://api.votesmart.org/docs/Committee.html
|
@@ -37,13 +101,13 @@ module GovKit
|
|
37
101
|
# If type_id is nil, defaults to all types.
|
38
102
|
# This method maps to Committee.getCommitteesByTypeState()
|
39
103
|
def self.find_by_type_and_state(type_id, state_abbrev)
|
40
|
-
response = get(
|
104
|
+
response = get('/Committee.getCommitteesByTypeState', :query => {'typeId' => type_id, 'stateId' => state_abbrev})
|
41
105
|
instantiate_record(response['committees'])
|
42
106
|
end
|
43
107
|
|
44
108
|
# Find a committee by VoteSmart committeeId. Maps to Committee.getCommittee()
|
45
109
|
def self.find(committee_id)
|
46
|
-
response = get(
|
110
|
+
response = get('/Committee.getCommittee', :query => {'committeeId' => committee_id})
|
47
111
|
instantiate_record(response['committee'])
|
48
112
|
end
|
49
113
|
end
|