campaign_cash 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/.gitignore +3 -0
- data/Gemfile +4 -0
- data/Rakefile +21 -0
- data/campaign_cash.gemspec +22 -0
- data/lib/campaign_cash.rb +11 -0
- data/lib/campaign_cash/base.rb +81 -0
- data/lib/campaign_cash/candidate.rb +80 -0
- data/lib/campaign_cash/committee.rb +74 -0
- data/lib/campaign_cash/version.rb +3 -0
- data/test/campaign_cash/test_candidate.rb +74 -0
- data/test/campaign_cash/test_committee.rb +59 -0
- data/test/test_helper.rb +22 -0
- metadata +96 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rake/testtask'
|
5
|
+
Rake::TestTask.new(:test) do |test|
|
6
|
+
test.libs << 'lib' << 'test'
|
7
|
+
test.pattern = 'test/**/test_*.rb'
|
8
|
+
test.verbose = true
|
9
|
+
end
|
10
|
+
|
11
|
+
task :default => :test
|
12
|
+
|
13
|
+
require 'rake/rdoctask'
|
14
|
+
Rake::RDocTask.new do |rdoc|
|
15
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
16
|
+
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = "campaign_cash #{version}"
|
19
|
+
rdoc.rdoc_files.include('README*')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path("../lib/campaign_cash/version", __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "campaign_cash"
|
6
|
+
s.version = CampaignCash::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ['Derek Willis']
|
9
|
+
s.email = ['dwillis@gmail.com']
|
10
|
+
s.homepage = "http://rubygems.org/gems/campaign_cash"
|
11
|
+
s.summary = "A thin client for The New York Times Campaign Finance API"
|
12
|
+
s.description = "Following the money."
|
13
|
+
|
14
|
+
s.required_rubygems_version = ">= 1.3.6"
|
15
|
+
s.rubyforge_project = "campaign_cash"
|
16
|
+
|
17
|
+
s.add_development_dependency "bundler", ">= 1.0.0"
|
18
|
+
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
21
|
+
s.require_path = 'lib'
|
22
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
module CampaignCash
|
5
|
+
|
6
|
+
end
|
7
|
+
|
8
|
+
require "#{File.dirname(__FILE__)}/campaign_cash/base"
|
9
|
+
require "#{File.dirname(__FILE__)}/campaign_cash/version"
|
10
|
+
require "#{File.dirname(__FILE__)}/campaign_cash/candidate"
|
11
|
+
require "#{File.dirname(__FILE__)}/campaign_cash/committee"
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'open-uri'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module CampaignCash
|
6
|
+
class Base
|
7
|
+
API_SERVER = 'api.nytimes.com'
|
8
|
+
API_VERSION = 'v3'
|
9
|
+
API_NAME = 'elections/us'
|
10
|
+
API_BASE = "/svc/#{API_NAME}/#{API_VERSION}/finances"
|
11
|
+
|
12
|
+
@@api_key = nil
|
13
|
+
@@copyright = nil
|
14
|
+
|
15
|
+
class << self
|
16
|
+
|
17
|
+
##
|
18
|
+
# The copyright footer to be placed at the bottom of any data from the New York Times. Note this is only set after an API call.
|
19
|
+
def copyright
|
20
|
+
@@copyright
|
21
|
+
end
|
22
|
+
|
23
|
+
def cycle
|
24
|
+
@@cycle
|
25
|
+
end
|
26
|
+
|
27
|
+
def base_uri
|
28
|
+
@@base_uri
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Set the API key used for operations. This needs to be called before any requests against the API. To obtain an API key, go to http://developer.nytimes.com/
|
33
|
+
def api_key=(key)
|
34
|
+
@@api_key = key
|
35
|
+
end
|
36
|
+
|
37
|
+
def api_key
|
38
|
+
@@api_key
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Builds a request URI to call the API server
|
43
|
+
def build_request_url(path, params)
|
44
|
+
URI::HTTP.build :host => API_SERVER,
|
45
|
+
:path => "#{API_BASE}/#{path}.json",
|
46
|
+
:query => params.map {|k,v| "#{k}=#{v}"}.join('&')
|
47
|
+
end
|
48
|
+
|
49
|
+
def invoke(path, params={})
|
50
|
+
begin
|
51
|
+
if @@api_key.nil?
|
52
|
+
raise "You must initialize the API key before you run any API queries"
|
53
|
+
end
|
54
|
+
|
55
|
+
full_params = params.merge 'api-key' => @@api_key
|
56
|
+
|
57
|
+
uri = build_request_url(path, full_params)
|
58
|
+
|
59
|
+
reply = uri.read
|
60
|
+
parsed_reply = JSON.parse reply
|
61
|
+
|
62
|
+
if parsed_reply.nil?
|
63
|
+
raise "Empty reply returned from API"
|
64
|
+
end
|
65
|
+
|
66
|
+
@@copyright = parsed_reply['copyright']
|
67
|
+
@@cycle = parsed_reply['cycle']
|
68
|
+
@@base_uri = parsed_reply['base_uri']
|
69
|
+
|
70
|
+
parsed_reply
|
71
|
+
rescue OpenURI::HTTPError => e
|
72
|
+
if e.message =~ /^404/
|
73
|
+
return nil
|
74
|
+
end
|
75
|
+
|
76
|
+
raise "Error connecting to URL #{uri} #{e}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module CampaignCash
|
2
|
+
class Candidate < Base
|
3
|
+
|
4
|
+
attr_reader :name, :id, :state, :district, :party, :fec_uri, :committee,
|
5
|
+
:mailing_city, :mailing_address, :mailing_state, :mailing_zip,
|
6
|
+
:total_receipts, :total_contributions, :total_from_individuals,
|
7
|
+
:total_from_pacs, :candidate_loans, :total_disbursements,
|
8
|
+
:total_refunds, :debts_owed, :begin_cash, :end_cash, :status,
|
9
|
+
:date_coverage_to, :date_coverage_from, :relative_uri
|
10
|
+
|
11
|
+
def initialize(params={})
|
12
|
+
params.each_pair do |k,v|
|
13
|
+
instance_variable_set("@#{k}", v)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.create_from_api(params={})
|
18
|
+
self.new :name => params['name'],
|
19
|
+
:id => params['id'],
|
20
|
+
:state => params['state'],
|
21
|
+
:district => params['district'],
|
22
|
+
:party => params['party'],
|
23
|
+
:fec_uri => params['fec_uri'],
|
24
|
+
:committee => params['committee'],
|
25
|
+
:mailing_city => params['mailing_city'],
|
26
|
+
:mailing_address => params['mailing_address'],
|
27
|
+
:mailing_state => params['mailing_state'],
|
28
|
+
:mailing_zip => params['mailing_zip'],
|
29
|
+
:total_receipts => params['total_receipts'],
|
30
|
+
:total_contributions => params['total_contributions'],
|
31
|
+
:total_from_individuals => params['total_from_individuals'],
|
32
|
+
:total_from_pacs => params['total_from_pacs'],
|
33
|
+
:candidate_loans => params['candidate_loans'],
|
34
|
+
:total_disbursements => params['total_disbursements'],
|
35
|
+
:total_refunds => params['total_refunds'],
|
36
|
+
:debts_owed => params['debts_owed'],
|
37
|
+
:begin_cash => params['begin_cash'],
|
38
|
+
:end_cash => params['end_cash'],
|
39
|
+
:status => params['status'],
|
40
|
+
:date_coverage_from => params['date_coverage_from'],
|
41
|
+
:date_coverage_to => params['date_coverage_to']
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.create_from_api_search_results(params={})
|
45
|
+
self.new :name => params['candidate']['name'],
|
46
|
+
:id => params['candidate']['id'],
|
47
|
+
:state => params['state'],
|
48
|
+
:district => params['district'],
|
49
|
+
:party => params['candidate']['party'],
|
50
|
+
:relative_uri => params['candidate']['relative_uri'],
|
51
|
+
:committee => params['committee']
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.find_by_fecid(cycle, fecid)
|
56
|
+
reply = invoke("#{cycle}/candidates/#{fecid}")
|
57
|
+
result = reply['results']
|
58
|
+
self.create_from_api(result.first) if result.first
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.leaders(cycle, category)
|
62
|
+
reply = invoke("#{cycle}/candidates/leaders/#{category}",{})
|
63
|
+
results = reply['results']
|
64
|
+
results.map{|c| self.create_from_api(c)}
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.search(cycle, name)
|
68
|
+
reply = invoke("#{cycle}/candidates/search", {:query => name})
|
69
|
+
results = reply['results']
|
70
|
+
results.map{|c| self.create_from_api_search_results(c)}
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.new_candidates(cycle)
|
74
|
+
reply = invoke("#{cycle}/candidates/new",{})
|
75
|
+
results = reply['results']
|
76
|
+
results.map{|c| self.create_from_api(c)}
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module CampaignCash
|
2
|
+
class Committee < Base
|
3
|
+
|
4
|
+
attr_reader :name, :id, :state, :district, :party, :fec_uri, :candidate,
|
5
|
+
:city, :address, :state, :zip, :relative_uri,
|
6
|
+
:total_receipts, :total_contributions, :total_from_individuals,
|
7
|
+
:total_from_pacs, :candidate_loans, :total_disbursements,
|
8
|
+
:total_refunds, :debts_owed, :begin_cash, :end_cash,
|
9
|
+
:date_coverage_to, :date_coverage_from
|
10
|
+
|
11
|
+
def initialize(params={})
|
12
|
+
params.each_pair do |k,v|
|
13
|
+
instance_variable_set("@#{k}", v)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.create_from_api(params={})
|
18
|
+
self.new :name => params['name'],
|
19
|
+
:id => params['id'],
|
20
|
+
:state => params['state'],
|
21
|
+
:party => params['party'],
|
22
|
+
:fec_uri => params['fec_uri'],
|
23
|
+
:city => params['city'],
|
24
|
+
:address => params['address'],
|
25
|
+
:zip => params['zip'],
|
26
|
+
:total_receipts => params['total_receipts'],
|
27
|
+
:total_contributions => params['total_contributions'],
|
28
|
+
:total_from_individuals => params['total_from_individuals'],
|
29
|
+
:total_from_pacs => params['total_from_pacs'],
|
30
|
+
:candidate_loans => params['candidate_loans'],
|
31
|
+
:total_disbursements => params['total_disbursements'],
|
32
|
+
:total_refunds => params['total_refunds'],
|
33
|
+
:debts_owed => params['debts_owed'],
|
34
|
+
:begin_cash => params['begin_cash'],
|
35
|
+
:end_cash => params['end_cash'],
|
36
|
+
:date_coverage_from => params['date_coverage_from'],
|
37
|
+
:date_coverage_to => params['date_coverage_to'],
|
38
|
+
:candidate => params['candidate']
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.create_from_api_search_results(params={})
|
42
|
+
self.new :name => params['name'],
|
43
|
+
:id => params['id'],
|
44
|
+
:city => params['city'],
|
45
|
+
:state => params['state'],
|
46
|
+
:zip => params['zip'],
|
47
|
+
:district => params['district'],
|
48
|
+
:party => params['party'],
|
49
|
+
:relative_uri => params['relative_uri'],
|
50
|
+
:candidate => params['candidate'],
|
51
|
+
:treasurer => params['treasurer']
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.find_by_fecid(cycle, fecid)
|
56
|
+
reply = invoke("#{cycle}/committees/#{fecid}")
|
57
|
+
result = reply['results']
|
58
|
+
self.create_from_api(result.first) if result.first
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.search(cycle, name)
|
62
|
+
reply = invoke("#{cycle}/committees/search", {:query => name})
|
63
|
+
results = reply['results']
|
64
|
+
results.map{|c| self.create_from_api_search_results(c)}
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.new_candidates(cycle)
|
68
|
+
reply = invoke("#{cycle}/committees/new",{})
|
69
|
+
results = reply['results']
|
70
|
+
results.map{|c| self.create_from_api(c)}
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper.rb'
|
2
|
+
|
3
|
+
class TestCampaignCash::TestCandidate < Test::Unit::TestCase
|
4
|
+
include CampaignCash
|
5
|
+
|
6
|
+
context "Candidate.create_from_api" do
|
7
|
+
setup do
|
8
|
+
reply = Base.invoke('2010/candidates/H4NY07011', {})
|
9
|
+
@result = reply['results'].first
|
10
|
+
@candidate = Candidate.create_from_api(@result)
|
11
|
+
end
|
12
|
+
|
13
|
+
should "return an object of the Candidate type" do
|
14
|
+
assert_kind_of(Candidate, @candidate)
|
15
|
+
end
|
16
|
+
|
17
|
+
%w(name id state district party fec_uri committee).each do |attr|
|
18
|
+
should "assign the value of the @#{attr} attribute from the '#{attr}' key in the hash" do
|
19
|
+
assert_equal(@result[attr], @candidate.send(attr))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "Candidate search" do
|
25
|
+
setup do
|
26
|
+
reply = Base.invoke('2010/candidates/search', {:query => "Udall"})
|
27
|
+
results = reply['results']
|
28
|
+
@candidates = results.map{|c| Candidate.create_from_api_search_results(c)}
|
29
|
+
end
|
30
|
+
|
31
|
+
should "return two candidate objects" do
|
32
|
+
assert_equal @candidates.size, 2
|
33
|
+
assert_kind_of(Candidate, @candidates.first)
|
34
|
+
assert_kind_of(Candidate, @candidates.last)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "New Candidates" do
|
39
|
+
setup do
|
40
|
+
reply = Base.invoke('2010/candidates/new', {})
|
41
|
+
results = reply['results']
|
42
|
+
@candidates = results.map{|c| Candidate.create_from_api(c)}
|
43
|
+
end
|
44
|
+
|
45
|
+
should "return 20 new candidates" do
|
46
|
+
assert_equal @candidates.size, 20
|
47
|
+
assert_kind_of(Candidate, @candidates.first)
|
48
|
+
assert_kind_of(Candidate, @candidates.last)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "candidate leaders" do
|
53
|
+
setup do
|
54
|
+
reply = Base.invoke('2010/candidates/leaders/end_cash', {})
|
55
|
+
results = reply['results']
|
56
|
+
@candidates = results.map{|c| Candidate.create_from_api(c)}
|
57
|
+
end
|
58
|
+
|
59
|
+
should "return 20 candidates each with a greater end_cash value than the next" do
|
60
|
+
assert (@candidates[0].end_cash >= @candidates[1].end_cash)
|
61
|
+
assert (@candidates[1].end_cash >= @candidates[2].end_cash)
|
62
|
+
assert (@candidates[2].end_cash >= @candidates[3].end_cash)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "request with missing cycle" do
|
67
|
+
should "return an error" do
|
68
|
+
assert_raise RuntimeError do
|
69
|
+
Base.invoke('/candidates/new', {})
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper.rb'
|
2
|
+
|
3
|
+
class TestCampaignCash::TestCommittee < Test::Unit::TestCase
|
4
|
+
include CampaignCash
|
5
|
+
|
6
|
+
context "Committee.create_from_api" do
|
7
|
+
setup do
|
8
|
+
reply = Base.invoke('2010/committees/C00312223', {})
|
9
|
+
@result = reply['results'].first
|
10
|
+
@committee = Committee.create_from_api(@result)
|
11
|
+
end
|
12
|
+
|
13
|
+
should "return an object of the Committee type" do
|
14
|
+
assert_kind_of(Committee, @committee)
|
15
|
+
end
|
16
|
+
|
17
|
+
%w(name id state party fec_uri candidate).each do |attr|
|
18
|
+
should "assign the value of the @#{attr} attribute from the '#{attr}' key in the hash" do
|
19
|
+
assert_equal(@result[attr], @committee.send(attr))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "Committee search" do
|
25
|
+
setup do
|
26
|
+
reply = Base.invoke('2010/committees/search', {:query => "Boeing"})
|
27
|
+
results = reply['results']
|
28
|
+
@committees = results.map{|c| Committee.create_from_api_search_results(c)}
|
29
|
+
end
|
30
|
+
|
31
|
+
should "return two committee objects" do
|
32
|
+
assert_equal @committees.size, 1
|
33
|
+
assert_kind_of(Committee, @committees.first)
|
34
|
+
assert_kind_of(Committee, @committees.last)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "New Committees" do
|
39
|
+
setup do
|
40
|
+
reply = Base.invoke('2010/committees/new', {})
|
41
|
+
results = reply['results']
|
42
|
+
@committees = results.map{|c| Committee.create_from_api_search_results(c)}
|
43
|
+
end
|
44
|
+
|
45
|
+
should "return 20 new committees" do
|
46
|
+
assert_equal @committees.size, 20
|
47
|
+
assert_kind_of(Committee, @committees.first)
|
48
|
+
assert_kind_of(Committee, @committees.last)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "request with missing id" do
|
53
|
+
should "return an error" do
|
54
|
+
assert_raise RuntimeError do
|
55
|
+
Base.invoke('2010/committees/', {})
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'shoulda'
|
4
|
+
require 'mocha'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
require File.dirname(__FILE__) + '/../lib/campaign_cash'
|
8
|
+
require File.dirname(__FILE__) + '/../lib/campaign_cash/base'
|
9
|
+
require File.dirname(__FILE__) + '/../lib/campaign_cash/candidate'
|
10
|
+
require File.dirname(__FILE__) + '/../lib/campaign_cash/committee'
|
11
|
+
|
12
|
+
# set your NYT Campaign Finance API key as an environment variable to run the tests
|
13
|
+
API_KEY = ENV['NYT_CAMPFIN_API_KEY']
|
14
|
+
CampaignCash::Base.api_key = API_KEY
|
15
|
+
|
16
|
+
def api_url_for(path, params = {})
|
17
|
+
full_params = params.merge 'api-key' => API_KEY
|
18
|
+
CampaignCash::Base.build_request_url(path, full_params).to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
module TestCampaignCash
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: campaign_cash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Derek Willis
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-12-03 00:00:00 -05:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: bundler
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 23
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 0
|
33
|
+
- 0
|
34
|
+
version: 1.0.0
|
35
|
+
type: :development
|
36
|
+
version_requirements: *id001
|
37
|
+
description: Following the money.
|
38
|
+
email:
|
39
|
+
- dwillis@gmail.com
|
40
|
+
executables: []
|
41
|
+
|
42
|
+
extensions: []
|
43
|
+
|
44
|
+
extra_rdoc_files: []
|
45
|
+
|
46
|
+
files:
|
47
|
+
- .gitignore
|
48
|
+
- Gemfile
|
49
|
+
- Rakefile
|
50
|
+
- campaign_cash.gemspec
|
51
|
+
- lib/campaign_cash.rb
|
52
|
+
- lib/campaign_cash/base.rb
|
53
|
+
- lib/campaign_cash/candidate.rb
|
54
|
+
- lib/campaign_cash/committee.rb
|
55
|
+
- lib/campaign_cash/version.rb
|
56
|
+
- test/campaign_cash/test_candidate.rb
|
57
|
+
- test/campaign_cash/test_committee.rb
|
58
|
+
- test/test_helper.rb
|
59
|
+
has_rdoc: true
|
60
|
+
homepage: http://rubygems.org/gems/campaign_cash
|
61
|
+
licenses: []
|
62
|
+
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
hash: 3
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
hash: 23
|
83
|
+
segments:
|
84
|
+
- 1
|
85
|
+
- 3
|
86
|
+
- 6
|
87
|
+
version: 1.3.6
|
88
|
+
requirements: []
|
89
|
+
|
90
|
+
rubyforge_project: campaign_cash
|
91
|
+
rubygems_version: 1.3.7
|
92
|
+
signing_key:
|
93
|
+
specification_version: 3
|
94
|
+
summary: A thin client for The New York Times Campaign Finance API
|
95
|
+
test_files: []
|
96
|
+
|