fech-ftp 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +79 -0
- data/Rakefile +6 -0
- data/fech-ftp.gemspec +31 -0
- data/lib/fech-ftp/candidate.rb +42 -0
- data/lib/fech-ftp/candidate_contribution.rb +13 -0
- data/lib/fech-ftp/committee.rb +35 -0
- data/lib/fech-ftp/committee_contribution.rb +15 -0
- data/lib/fech-ftp/individual_contribution.rb +13 -0
- data/lib/fech-ftp/table.rb +128 -0
- data/lib/fech-ftp/table_methods.rb +16 -0
- data/lib/fech-ftp/version.rb +5 -0
- data/lib/fech-ftp.rb +28 -0
- data/test/cm.txt +7 -0
- data/test/cn.txt +10 -0
- data/test/itcont.txt +9 -0
- data/test/test_candidate.rb +27 -0
- data/test/test_committee.rb +36 -0
- data/test/test_individual.rb +27 -0
- data/test/webk.txt +9 -0
- data/test/webl.txt +17 -0
- metadata +215 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b1921cd5fbeae654fe3ce6a142914b6c20cce674
|
4
|
+
data.tar.gz: 3390d96ba890e335478fc4f68968f7cb1ee383ee
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dc3c7e63d9c5f0d158e3c83872129f47ce2c79f72d50145f43c61dd50826a1850107b1b68c246e161739c4b17d10456c273d0ed356fcc2619a3f2c6227872628
|
7
|
+
data.tar.gz: 0ba4c5ffb8dc5078525b8b6acd41066abcfdabdd2b9fe4540183c2c25c71508ac55d3e5c1b9cbfabc879b8c558c069cb86d520157d559d3a336d2162b44392df
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Derek Willis
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# fech-ftp
|
2
|
+
|
3
|
+
A Ruby library for retrieving and parsing [FTP data downloads](http://www.fec.gov/finance/disclosure/ftp_download.shtml) from the Federal Election Commission. While fech-ftp provides an API to some transaction data (contributions from a committee to a candidate and contributions between two committees), its main purpose is to provide a simple interface to the "[committee master](http://www.fec.gov/finance/disclosure/metadata/DataDictionaryCommitteeMaster.shtml)" and "[candidate master](http://www.fec.gov/finance/disclosure/metadata/DataDictionaryCandidateMaster.shtml)" files, with the ultimate goal of providing a way to connect individual transactions parsed by [Fech](https://github.com/NYTimes/Fech) with their canonical recipients.
|
4
|
+
|
5
|
+
fech-ftp is tested under Ruby 2.0.0, 2.1.X and 2.2.X.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'fech-ftp'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install fech-ftp
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Fech-FTP can be used by itself or in combination with Fech. To retrieve canonical details about candidates for an election cycle, pass the cycle into the following constructor:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require 'fech-ftp'
|
27
|
+
cands = Fech::Candidate.detail(2014)
|
28
|
+
cands.first # => {:candidate_id=>"H0AK00097", :candidate_name=>"COX, JOHN ROBERT", :party=>"REP", :election_year=>"2012", :office_state=>"AK", :office=>"H", :district=>"00", :incumbent_challenger_status=>"C", :candidate_status=>"N", :committee_id=>"C00525261", :street_one=>"PO BOX 1092", :street_two=>"", :city=>"ANCHOR POINT", :state=>"AK", :zipcode=>"995561092"}
|
29
|
+
```
|
30
|
+
|
31
|
+
If you want to have the data transferred into an csv, add the property `format: :csv`, like so:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
Fech::Candidate.detail(2014, format: :csv)
|
35
|
+
```
|
36
|
+
|
37
|
+
You can specify the location that the FEC zip files opened by fech-ftp are downloaded by adding the property `location`, with an absolute path to a directory that must include a trailing slash, like so:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
Fech::Candidate.detail(2014, location: "/tmp/fec/")
|
41
|
+
```
|
42
|
+
|
43
|
+
If you are using the [Sequel Gem](https://github.com/jeremyevans/sequel), you can pass in the DB table object as the `connection` property:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
Fech::Candidate.detail(2014, format: :db, connection: DB[:candidates])
|
47
|
+
```
|
48
|
+
|
49
|
+
Please note that it assumes the table object's columns == header properties for the data that gets passed in. Otherwise, an exception will be thrown.
|
50
|
+
To get around this, you can provide the `connection` property as an array, with the traditional `DB` constant value being the in the first element, followed by the table name:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
Fech::Candidate.detail(2014, format: :db, connection: [<DATABASE OBJECT>, :candidates])
|
54
|
+
```
|
55
|
+
|
56
|
+
The table will automatically be created, and then will be populated with the selected dataset. Also please note that it assumes there are no foreign keys. To add them, please follow the Sequel documentation guidelines for adding/altering foreign keys.
|
57
|
+
|
58
|
+
`Fech::Candidate` and `Fech::Committee` each have multiple datasets available and can be accessed using the corresponding method:
|
59
|
+
|
60
|
+
`Candidate` responds to `summary_current, summary_all, detail`
|
61
|
+
`Committee` responds to `linkage, summary_all, detail`
|
62
|
+
|
63
|
+
The following have only a single dataset but will respond to any of the above methods:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
Fech::CandidateContribution
|
67
|
+
Fech::IndividualContribution
|
68
|
+
Fech::CommitteeContribution
|
69
|
+
```
|
70
|
+
|
71
|
+
There are additional classes representing [PAC contributions to candidates](http://www.fec.gov/finance/disclosure/metadata/DataDictionaryContributionstoCandidates.shtml) (`CandidateContribution`) and [transactions involving two committees](http://www.fec.gov/finance/disclosure/metadata/DataDictionaryCommitteetoCommittee.shtml) (`CommitteeContribution`). Be advised that both of the FTP files loaded by these classes are large and can take minutes to parse. They are appropriately used for background processing or data loading purposes, not for providing a live API. Individual Contributions in particular runs in excess of 1-2 million rows of data (~ 200mb)
|
72
|
+
|
73
|
+
## Contributing
|
74
|
+
|
75
|
+
1. Fork it ( http://github.com/dwillis/fech-ftp/fork )
|
76
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
77
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
78
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
79
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/fech-ftp.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'fech-ftp/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "fech-ftp"
|
8
|
+
spec.version = Fech::Ftp::VERSION
|
9
|
+
spec.authors = ["Derek Willis"]
|
10
|
+
spec.email = ["dwillis@gmail.com"]
|
11
|
+
spec.summary = %q{A Ruby interface for FTP data from the Federal Election Commission.}
|
12
|
+
spec.description = %q{Retrieve and parse summary and detailed federal campaign finance data.}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "minitest"
|
24
|
+
spec.add_dependency "fech"
|
25
|
+
spec.add_dependency "remote_table"
|
26
|
+
spec.add_dependency "american_date"
|
27
|
+
spec.add_dependency "sqlite3"
|
28
|
+
spec.add_dependency "sequel"
|
29
|
+
spec.add_dependency "rubyzip"
|
30
|
+
spec.add_dependency "activesupport"
|
31
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Fech
|
2
|
+
class Candidate < Table
|
3
|
+
HEADERS = {
|
4
|
+
detail: {
|
5
|
+
file: 'cn',
|
6
|
+
headers: [
|
7
|
+
:candidate_id, :candidate_name, :party, :election_year,
|
8
|
+
:office_state, :office, :district, :incumbent_challenger_status,
|
9
|
+
:candidate_status, :committee_id, :street_one, :street_two, :city,
|
10
|
+
:state, :zipcode
|
11
|
+
]
|
12
|
+
},
|
13
|
+
summary_current: {
|
14
|
+
file: 'webl',
|
15
|
+
headers: [
|
16
|
+
:candidate_id, :candidate_name, :status, :party_code, :party,
|
17
|
+
:total_receipts, :transfers_from_authorized, :total_disbursements,
|
18
|
+
:transfers_to_authorized, :beginning_cash, :ending_cash, :candidate_contributions,
|
19
|
+
:candidate_loans, :other_loans, :candidate_loan_repayments, :other_loan_repayments,
|
20
|
+
:debts_owed_by, :total_individual_contributions, :office_state, :district,
|
21
|
+
:special_election_status, :primary_election_status, :runoff_election_status,
|
22
|
+
:general_election_status, :general_election_percent, :pac_contributions,
|
23
|
+
:party_contributions, :coverage_end_date, :individual_refunds, :committee_refunds
|
24
|
+
]
|
25
|
+
},
|
26
|
+
summary_all: {
|
27
|
+
file: 'weball',
|
28
|
+
headers: [
|
29
|
+
:candidate_id, :candidate_name, :status, :party_code, :party,
|
30
|
+
:total_receipts, :transfers_from_authorized, :total_disbursements,
|
31
|
+
:transfers_to_authorized, :beginning_cash, :ending_cash, :candidate_contributions,
|
32
|
+
:candidate_loans, :other_loans, :candidate_loan_repayments, :other_loan_repayments,
|
33
|
+
:debts_owed_by, :total_individual_contributions, :office_state, :district,
|
34
|
+
:special_election_status, :primary_election_status, :runoff_election_status,
|
35
|
+
:general_election_status, :general_election_percent, :pac_contributions,
|
36
|
+
:party_contributions, :coverage_end_date, :individual_refunds, :committee_refunds
|
37
|
+
]
|
38
|
+
}
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Fech
|
2
|
+
class CandidateContribution < Table
|
3
|
+
HEADERS = {
|
4
|
+
file: "oth",
|
5
|
+
headers: [
|
6
|
+
:committee_id, :amendment, :report_type, :primary_general, :microfilm,
|
7
|
+
:transaction_type, :entity_type, :name, :city, :state, :zipcode,
|
8
|
+
:employer, :occupation, :transaction_date, :amount, :other_committee_id, :candidate_id,
|
9
|
+
:transaction_id, :filing_id, :memo_code, :memo_text, :fec_record_number
|
10
|
+
]
|
11
|
+
}
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Fech
|
2
|
+
class Committee < Table
|
3
|
+
HEADERS = {
|
4
|
+
detail: {
|
5
|
+
file: 'cm',
|
6
|
+
headers: [
|
7
|
+
:committee_id, :committee_name, :treasurer, :street_one,
|
8
|
+
:street_two,:city, :state, :zipcode, :designation, :type, :party,
|
9
|
+
:filing_frequency, :category, :connected_organization, :candidate_id
|
10
|
+
]
|
11
|
+
},
|
12
|
+
summary_all: {
|
13
|
+
file: 'webk',
|
14
|
+
headers: [
|
15
|
+
:committee_id, :committee_name, :type, :designation, :filing_frequency,
|
16
|
+
:total_receipts, :transfers_from_affiliates, :individual_contributions,
|
17
|
+
:pac_contributions, :candidate_contributions, :candidate_loans,
|
18
|
+
:total_loans_received, :total_disbursements, :transfers_to_affiliates,
|
19
|
+
:individual_refunds, :committee_refunds, :candidate_loan_repayments,
|
20
|
+
:loan_repayments, :beginning_year_cash, :ending_cash, :debts_owed_by,
|
21
|
+
:nonfederal_transfers_received, :contributions_to_committees,
|
22
|
+
:independent_expenditures, :party_coordinated_expenditures,
|
23
|
+
:nonfederal_share_expenditures, :coverage_end_date
|
24
|
+
]
|
25
|
+
},
|
26
|
+
linkage: {
|
27
|
+
file: 'ccl',
|
28
|
+
headers: [
|
29
|
+
:committee_id, :candidate_election_year, :election_year,
|
30
|
+
:candidate_id, :type, :designation, :linkage_id
|
31
|
+
]
|
32
|
+
}
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Fech
|
2
|
+
class CommitteeContribution < Table
|
3
|
+
HEADERS = {
|
4
|
+
detail: {
|
5
|
+
file: "oth",
|
6
|
+
headers: [
|
7
|
+
:committee_id, :amendment, :report_type, :primary_general, :microfilm,
|
8
|
+
:transaction_type, :entity_type, :name, :city, :state, :zipcode,
|
9
|
+
:employer, :occupation, :transaction_date, :amount, :other_committee_id,
|
10
|
+
:transaction_id, :filing_id, :memo_code, :memo_text, :fec_record_number
|
11
|
+
]
|
12
|
+
}
|
13
|
+
}
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Fech
|
2
|
+
class IndividualContribution < Table
|
3
|
+
HEADERS = {
|
4
|
+
file: 'indiv',
|
5
|
+
headers: [
|
6
|
+
:committee_id, :amendment_indicator, :report_type, :election_type,
|
7
|
+
:image_number, :trans_type, :entity_type, :name, :city, :state, :zip,
|
8
|
+
:employer, :occupation, :trans_date, :trans_amount, :other_id, :trans_id,
|
9
|
+
:filing_id, :memo_cd, :memo_txt, :fec_record_number
|
10
|
+
]
|
11
|
+
}
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module Fech
|
2
|
+
class Table
|
3
|
+
def initialize(cycle, opts={})
|
4
|
+
@cycle = cycle
|
5
|
+
@headers = opts[:headers]
|
6
|
+
@file = opts[:file]
|
7
|
+
@format = opts[:format]
|
8
|
+
@location = opts[:location]
|
9
|
+
@receiver = opts[:connection] || receiver
|
10
|
+
@parser = parser
|
11
|
+
end
|
12
|
+
|
13
|
+
def receiver
|
14
|
+
if @format == :csv
|
15
|
+
CSV.open("#{@file}#{@cycle.to_s[2..3]}.csv", 'a+', headers: @headers, write_headers: true)
|
16
|
+
else
|
17
|
+
[]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def retrieve_data
|
22
|
+
fetch_file { |row| enter_row(row) }
|
23
|
+
return @receiver
|
24
|
+
end
|
25
|
+
|
26
|
+
def enter_row(row)
|
27
|
+
case @format
|
28
|
+
when :db
|
29
|
+
table_exist? ? @receiver << row : create_table(row)
|
30
|
+
when :csv
|
31
|
+
@receiver << row.values
|
32
|
+
else
|
33
|
+
@receiver << row
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# the @receiver obj is the database itself.
|
38
|
+
# This assumes the table needs to be created.
|
39
|
+
|
40
|
+
def table_exist?
|
41
|
+
@receiver.respond_to? :columns
|
42
|
+
end
|
43
|
+
|
44
|
+
def create_table(row)
|
45
|
+
db, table = @receiver
|
46
|
+
table = table.to_s.pluralize.to_sym
|
47
|
+
db.create_table(table) { primary_key :id }
|
48
|
+
|
49
|
+
row.each do |k,v|
|
50
|
+
v = v.nil? ? String : v.class
|
51
|
+
db.alter_table table do
|
52
|
+
add_column k, v
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
@receiver = db[table]
|
57
|
+
@receiver << row
|
58
|
+
end
|
59
|
+
|
60
|
+
def fetch_file(&blk)
|
61
|
+
zip_file = "#{@file}#{@cycle.to_s[2..3]}.zip"
|
62
|
+
Net::FTP.open("ftp.fec.gov") do |ftp|
|
63
|
+
ftp.login
|
64
|
+
ftp.chdir("./FEC/#{@cycle}")
|
65
|
+
begin
|
66
|
+
ftp.get(zip_file, "./#{zip_file}")
|
67
|
+
rescue Net::FTPPermError
|
68
|
+
raise 'File not found - please try the other methods'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
unzip(zip_file, &blk)
|
73
|
+
end
|
74
|
+
|
75
|
+
def parser
|
76
|
+
@headers.map.with_index do |h,i|
|
77
|
+
if h.to_s =~ /cash|amount|contributions|total|loan|transfer|debts|refund|expenditure/
|
78
|
+
[h, ->(line) { line[i].to_f }]
|
79
|
+
elsif h == :filing_id
|
80
|
+
[h, ->(line) { line[i].to_i }]
|
81
|
+
elsif h.to_s =~ /_date/
|
82
|
+
[h, ->(line) { parse_date(line[i]) }]
|
83
|
+
else
|
84
|
+
[h, ->(line) { line[i] }]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def format_row(line)
|
90
|
+
hash = {}
|
91
|
+
line = line.encode('UTF-8', invalid: :replace, replace: ' ').chomp.split("|")
|
92
|
+
|
93
|
+
@parser.each { |k,blk| hash[k] = blk.call(line) }
|
94
|
+
|
95
|
+
return hash
|
96
|
+
end
|
97
|
+
|
98
|
+
def parse_date(date)
|
99
|
+
if date == '' && table_exist?
|
100
|
+
if table_exist?
|
101
|
+
return Date.new(@cycle, 1,1)
|
102
|
+
else
|
103
|
+
return ''
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
if date.length == 8
|
108
|
+
Date.strptime(date, "%m%d%Y")
|
109
|
+
else
|
110
|
+
Date.parse(date)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def unzip(zip_file, &blk)
|
115
|
+
Zip::File.open(zip_file) do |zip|
|
116
|
+
zip.each do |entry|
|
117
|
+
path = @location.nil? ? entry.name : @location + entry.name
|
118
|
+
entry.extract(path) if !File.file?(path)
|
119
|
+
File.delete(zip_file)
|
120
|
+
File.foreach(path) do |row|
|
121
|
+
blk.call(format_row(row))
|
122
|
+
end
|
123
|
+
File.delete(path)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Fech
|
2
|
+
class Table
|
3
|
+
class_eval do
|
4
|
+
[:detail, :summary_all, :linkage, :summary_current].each do |meth|
|
5
|
+
action = lambda do |cycle, opts={}|
|
6
|
+
attrs = self::HEADERS[meth] || self::HEADERS
|
7
|
+
attrs.merge!(opts)
|
8
|
+
table = new(cycle, attrs)
|
9
|
+
table.retrieve_data
|
10
|
+
end
|
11
|
+
|
12
|
+
define_singleton_method(meth, action)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/fech-ftp.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'fech'
|
2
|
+
require "fech-ftp/version"
|
3
|
+
require "fech-ftp/table"
|
4
|
+
require "fech-ftp/committee"
|
5
|
+
require "fech-ftp/candidate"
|
6
|
+
require "fech-ftp/candidate_contribution"
|
7
|
+
require "fech-ftp/committee_contribution"
|
8
|
+
require "fech-ftp/individual_contribution"
|
9
|
+
require "fech-ftp/table_methods"
|
10
|
+
require "net/ftp"
|
11
|
+
require 'zip'
|
12
|
+
require 'active_support'
|
13
|
+
require 'active_support/deprecation'
|
14
|
+
require 'remote_table'
|
15
|
+
require 'american_date'
|
16
|
+
require 'sqlite3'
|
17
|
+
require 'sequel'
|
18
|
+
require 'csv'
|
19
|
+
|
20
|
+
module Fech
|
21
|
+
class Utilities
|
22
|
+
def self.superpacs
|
23
|
+
url = "http://www.fec.gov/press/press2011/ieoc_alpha.shtml"
|
24
|
+
t = RemoteTable.new url, :row_xpath => '//table/tr', :column_xpath => 'td', :encoding => 'windows-1252', :headers => %w{ row_id committee_id committee_name filing_frequency}
|
25
|
+
t.entries
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/test/cm.txt
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
C00008896|OPEIU LOCAL 153 "VOTE" (VOICE OF THE ELECTORATE) COMMITTEE|RICHARD J LANIGAN|265 WEST 14TH ST.||NEW YORK|NY|10011|U|Q||Q|L|EMPLOYEES INT'L UNION; OFFICE & PROF.|
|
2
|
+
C00009282|NORFOLK SOUTHERN CORPORATION GOOD GOVERNMENT FUND|LEDOUX, MARQUE|ONE CONSTITUTION AVE NE||WASHINGTON|DC|20002|B|Q|UNK|M|C|NORFOLK SOUTHERN CORPORATION|
|
3
|
+
C00009357|THE RECORDING INDUSTRY ASSOCIATION OF AMERICA POLITICAL ACTION COMMITTEE|GLAZIER, MITCH|1025 F STREET NW|10TH FLOOR|WASHINGTON|DC|20004|B|Q||Q|T|THE RECORDING INDUSTRY ASSOCIATION OF AMERICA, INC.|
|
4
|
+
C00009423|LAND O'LAKES, INC., PAC|GRABOW, KAREN|P.O. BOX 64101||ST. PAUL|MN|55164|B|Q||Q|V|LAND O'LAKES, INC.|
|
5
|
+
C00009456|3RD CONGRESSIONAL DISTRICT DEMOCRATIC PARTY OF WISCONSIN|UGLAND, GERALD DAVID MR.|2450 RIVER BEND ROAD||PLOVER|WI|544672728|U|Y|DEM|Q||DEMOCRATIC PARTY OF WISCONSIN|
|
6
|
+
C00009597|NATIONAL COUNCIL OF COAL LESSORS INC PAC|CRAWFORD, THOMAS|101 CONSTITUTION AVENUE NW|SUITE 900|WASHINGTON|DC|20001|U|Q||A|T|COAL LESSORS INC; NAT'L COUNCIL OF|
|
7
|
+
C00277525|JERRY CARROLL "S" COMMITTEE|JERRY CARROLL|PO BOX 9079||STOCKTON|CA|95208|P|S|IND|A|||S2CA00591
|
data/test/cn.txt
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
H0AK00097|COX, JOHN ROBERT|REP|2012|AK|H|00|C|N|C00525261|PO BOX 1092||ANCHOR POINT|AK|995561092
|
2
|
+
H0AL02087|ROBY, MARTHA|REP|2014|AL|H|02|I|C|C00462143|3260 BANKHEAD AVE||MONTGOMERY|AL|361062448
|
3
|
+
H0AL05049|CRAMER, ROBERT E "BUD" JR|DEM|2008|AL|H|05|I|P|C00239038|PO BOX 2621||HUNTSVILLE|AL|35804
|
4
|
+
H0AL05163|BROOKS, MO|REP|2014|AL|H|05|I|C|C00464149|7610 FOXFIRE DR.||HUNTSVILLE|AL|35802
|
5
|
+
H0AL05189|SHEPARD, TAZEWELL|DEM|2010|AL|H|05|C|P|C00477026|303 WILLIAMS AVE|SUITE 1311|HUNTSVILLE|AL|35801
|
6
|
+
H0AL06088|COOKE, STANLEY KYLE|REP|2010|AL|H|06|C|N|C00464222|723 CHERRY BROOK ROAD||KIMBERLY|AL|35091
|
7
|
+
H0AL07086|SEWELL, TERRI A.|DEM|2014|AL|H|07|I|C|C00458976|P.O. BOX 1964||BIRMINGHAM|AL|35201
|
8
|
+
H0AL07094|HILLIARD, EARL FREDERICK JR|DEM|2010|AL|H|07|O|P|C00460410|PO BOX 12804||BIRMINGHAM|AL|35202
|
9
|
+
H0AL07177|CHAMBERLAIN, DON|REP|2012|AL|H|07|C|P|C00482059|512 LAPSLEY ST||SELMA|AL|36701
|
10
|
+
H0AR01083|CRAWFORD, ERIC ALAN RICK|REP|2014|AR|H|01|I|C|C00462374|34 CR 455||JONESBORO|AR|72404
|
data/test/itcont.txt
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
C00492371|N|M2|P|11990223949|15|IND|BIRDWELL, BRAD A.|CYPRESS|TX|77429|BIRDWELL|CONTRACTOR|01232011|500||SA17A.4153|714660|||4021720111136021419
|
2
|
+
C00492371|N|M2|P|11990223955|15|IND|OVERMAN, JOE E.|PACOFIC|MT|63069|ET SECURITY|PILOT|01232011|250||SA17A.4151|714660|||4021720111136021438
|
3
|
+
C00410266|N|M2||11930387712|15|IND|HIGGINS, THOMAS|MALVERN|PA|19355|THE VANGUARD GROUP|ACCOUNTANT|01042011|600||AC9DB5EBA79C54DED937|714732|||4031620111137408276
|
4
|
+
C00410266|N|M2||11930387715|15|IND|NORRIS, ELIZABETH A|MALVERN|PA|19355||INFORMATION REQUESTED|01132011|4000||AD2BAAB7CE6234AA585D|714732|||4031620111137408284
|
5
|
+
C00410266|N|M2||11930387715|15|IND|NORRIS, JAMES|MALVERN|PA|19355|THE VANGUARD GROUP|MANAGER|01042011|4000||A1B7AADE1665546EB8AF|714732|||4031620111137408285
|
6
|
+
C00410266|N|M2||11930387716|15|IND|POLLOCK, RANDALL|MALVERN|PA|19355|VANGUARD GROUP|INVESTMENT COMPANY EXECUTIVE|01122011|250||AC184E2EB48E14A4991F|714732|||4031620111137408288
|
7
|
+
C00410266|N|M2||11930387717|15|IND|REED, GLENN|MALVERN|PA|19355|VANGUARD|INVESTMENT COMPANY EXECUTIVE|01042011|4000||AC8B80FC4AF714F49911|714732|||4031620111137408289
|
8
|
+
C00410266|N|M2||11930387720|15|IND|WHITAKER, BARRY|MALVERN|PA|19355|VANGUARD|INVESTMENT COMPANY EXECUTIVE|01102011|700||A2F0D333DFECA4369933|714732|||4031620111137408298
|
9
|
+
C00109546|N|M2||11990225012|15|IND|BOWERS, KIMBERLY S|SAN ANTONIO|TX|78249|VALERO SERVICES, INC.|EVP & GENERAL COUNSEL|01312011|205||INCA281987|714749|||4031620111137409615
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'fech-ftp'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
class TestCandidate < MiniTest::Test
|
5
|
+
def setup
|
6
|
+
detail_file = File.readlines('test/cn.txt').to_a
|
7
|
+
candidate_detail = Fech::Candidate.new(2012, headers: Fech::Candidate::HEADERS[:detail][:headers])
|
8
|
+
|
9
|
+
summary_file = File.readlines('test/webl.txt').to_a
|
10
|
+
candidate_summary = Fech::Candidate.new(2012, headers: Fech::Candidate::HEADERS[:summary_current][:headers])
|
11
|
+
|
12
|
+
@detail_row = candidate_detail.format_row(detail_file[3])
|
13
|
+
@summary_row = candidate_summary.format_row(summary_file[3])
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_candidate_id_loads_properly
|
17
|
+
assert @detail_row.fetch(:candidate_id) == "H0AL05163"
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_candidate_dollar_amts_are_floats
|
21
|
+
assert_kind_of Float, @summary_row.fetch(:total_receipts)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_that_summary_creates_dates
|
25
|
+
assert_equal Date.parse('11/27/2013'), @summary_row.fetch(:coverage_end_date)
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'fech-ftp'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
class TestCommittee < MiniTest::Test
|
5
|
+
def setup
|
6
|
+
db = Sequel.sqlite # synonymous with Sequel.connect; test assumes the table was not created yet.
|
7
|
+
detail_file = File.readlines('test/cm.txt').to_a
|
8
|
+
detail_head = Fech::Committee::HEADERS[:detail][:headers]
|
9
|
+
|
10
|
+
cm_detail = Fech::Committee.new(2012, headers: detail_head)
|
11
|
+
@db_test = Fech::Committee.new(2012, headers: detail_head, format: :db, connection: [db, :committee])
|
12
|
+
|
13
|
+
summary_file = File.readlines('test/webk.txt').to_a
|
14
|
+
cm_summary = Fech::Committee.new(2012, headers: Fech::Committee::HEADERS[:summary_all][:headers])
|
15
|
+
|
16
|
+
@summary_row = cm_summary.format_row(summary_file[1])
|
17
|
+
@detail_row = cm_detail.format_row(detail_file[1])
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_that_db_option_is_formatted_correctly
|
21
|
+
@db_test.create_table(@summary_row)
|
22
|
+
assert_equal @db_test.table_exist?, true
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_that_committee_detail_is_properly_loaded
|
26
|
+
assert_equal "NORFOLK SOUTHERN CORPORATION GOOD GOVERNMENT FUND", @detail_row.fetch(:committee_name)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_that_summary_creates_dates
|
30
|
+
assert_equal Date.parse('06/30/2013'), @summary_row.fetch(:coverage_end_date)
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_that_amount_cols_are_floats
|
34
|
+
assert_kind_of Float, @summary_row.fetch(:total_receipts)
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'fech-ftp'
|
2
|
+
require 'minitest/autorun'
|
3
|
+
|
4
|
+
class TestIndividual < Minitest::Test
|
5
|
+
def setup
|
6
|
+
indiv_file = File.readlines('test/itcont.txt').to_a
|
7
|
+
indiv_table = Fech::IndividualContribution.new(2012, headers: Fech::IndividualContribution::HEADERS[:headers])
|
8
|
+
|
9
|
+
@row = indiv_table.format_row(indiv_file[0])
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_dollar_amts_are_floats
|
13
|
+
assert_kind_of Float, @row.fetch(:trans_amount)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_filing_id_are_integers
|
17
|
+
assert_kind_of Integer, @row.fetch(:filing_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_date_parses_properly
|
21
|
+
assert_equal Date.strptime('01232011', "%m%d%Y"), @row.fetch(:trans_date)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_fec_record_number_matches
|
25
|
+
assert_equal "4021720111136021419", @row.fetch(:fec_record_number)
|
26
|
+
end
|
27
|
+
end
|
data/test/webk.txt
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
C00494757|AMERICA'S FUTURE FUND PAC|N|D|Q|2200|0|2000|200|0|0|0|40002.5|0|0|0|0|0|38504.58|702.08|0|0|5000|0|0|0|09/30/2013
|
2
|
+
C00492025|AMERICAN DEFENSE AND MILITARY PAC (ADAM PAC)|N|D|Q|12500|0|0|12500|0|0|0|8757.67|0|0|0|0|0|7841.79|11584.12|0|0|5000|0|0|0|06/30/2013
|
3
|
+
C00553271|AMERICAN LEADERSHIP NOW (ALN PAC)|N|D|Q||||||||||||||||||||||
|
4
|
+
C00495150|AMERICAN LIBERTY AND NATION PAC (ALAN PAC)|N|D|Q|39200|34200|0|5000|0|0|0|17109.98|0|0|0|0|0|6787.9|28877.92|0|0|17000|0|0|0|06/30/2013
|
5
|
+
C00439521|AMERICAN SECURITY PAC|N|D|Q|25000|0|0|25000|0|0|0|25522.06|0|0|0|0|0|3241.23|2719.17|0|0|2500|0|0|0|09/30/2013
|
6
|
+
C00527846|ANN MARIE PAC|N|D|Q|0|0|0|0|0|0|0|3307.75|0|0|0|0|0|10703.71|7395.96|0|0|0|0|0|0|06/30/2013
|
7
|
+
C00531764|ANN PAC|N|D|Q|67045|0|15045|52000|0|0|0|17636.26|0|0|0|0|0|1000|50408.74|0|0|2000|0|0|0|09/30/2013
|
8
|
+
C00540062|ANNIEPAC|N|D|Q|5000|0|0|5000|0|0|0|415|0|0|0|0|0|25|4610|0|0|0|0|0|0|06/30/2013
|
9
|
+
C00524777|APAC|N|D|Q|0|0|0|0|0|0|0|10151.53|0|0|0|0|0|10262.8|111.27|0|0|0|0|0|0|06/30/2013
|
data/test/webl.txt
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
H2AK00101|MOORE, MATTHEW EDWARD|C|1|DEM|15749.5|0|13376.95|0|0|2372.55|0|12000|0|0|0|12100|3741.5|AK|00||||||0|0|09/30/2013|0|0
|
2
|
+
H4AK00123|DUNBAR, FORREST|C|1|DEM|21805.01|0|3225|0|0|18580.01|0|0|0|0|0|0|21805.01|AK|00||||||0|0|09/30/2013|0|0
|
3
|
+
H6AK00045|YOUNG, DONALD E|I|2|REP|300676.14|0|176268.29|0|508299.46|632707.31|0|0|0|0|0|0|210896.02|AK|00||||||88828.14|0|09/30/2013|1000|0
|
4
|
+
H4AL01156|LEFLORE, BURTON|O|1|DEM|12581|0|11276|0|0|1304|4932|0|0|0|0|3081|12581|AL|01||||||0|0|11/27/2013|0|0
|
5
|
+
H2AL01077|BONNER, JOSIAH ROBINS JR.|I|2|REP|85681.86|0|207065.54|0|157209.22|35825.54|0|0|0|0|0|0|37650|AL|01||||||48000|0|09/30/2013|750|0
|
6
|
+
H2AL01176|YOUNG, LARRY DEAN JR|O|2|REP|260046.54|0|226818.07|0|0|33228.47|0|174500|0|75000|0|99500|85546.54|AL|01||||||0|0|10/16/2013|0|0
|
7
|
+
H4AL01123|BYRNE, BRADLEY ROBERTS|I|2|REP|1119799.1|0|983582.56|0|0|136216.54|0|0|0|0|0|75063.68|708698.11|AL|01|W|||||411100.99|0|11/27/2013|3000|2500
|
8
|
+
H4AL01131|JAMES, JESSICA|C|2|REP|10113|0|10113|0|0|0|0|0|0|0|0|0|10113|AL|01||||||0|0|12/31/2013|0|0
|
9
|
+
H4AL01149|FINCHER, CHAD|O|2|REP|158282.35|0|153133.28|0|0|5149.07|0|10000|0|0|0|10000|138635|AL|01||||||9500|0|09/30/2013|300|0
|
10
|
+
H4AL01172|GRIFFITH, PRESTON WELLS III|O|2|REP|209780.99|0|184705.42|0|0|25075.57|0|0|0|0|0|19422.81|196780.99|AL|01||||||13000|0|09/30/2013|0|0
|
11
|
+
H4AL01180|POWE, SHARON L|O|2|REP|5450|0|4931|0|5000|519|0|0|0|0|0|0|5450|AL|01||||||0|0|09/12/2013|0|0
|
12
|
+
H2AL01192|RAILEY, CURTIS MONROE|C|3|IND|0|0|1150.74|0|2368.57|1217.83|0|0|0|0|0|10000|0|AL|01||||||0|0|06/30/2013|0|0
|
13
|
+
H0AL02087|ROBY, MARTHA|I|2|REP|497600.35|31.25|202341.17|0|186496.35|481755.53|0|0|0|0|0|0|250003.52|AL|02||||||243188.7|0|09/30/2013|25|1000
|
14
|
+
H2AL03032|ROGERS, MICHAEL|I|2|REP|308853.99|0|257847.29|0|292048.29|343054.99|0|0|0|0|0|0|91328.35|AL|03||||||215390|1000|09/30/2013|0|0
|
15
|
+
H2AL07165|NORRIS, PHILLIP DWIGHT|C|2|REP|100|0|50|0|0|50|0|0|0|0|0|0|100|AL|04||||||0|0|12/31/2013|0|0
|
16
|
+
H6AL04098|ADERHOLT, ROBERT B. REP.|I|2|REP|504485.15|0|327299.7|0|152881.82|330067.27|0|0|0|0|0|0|192597.05|AL|04||||||311128.84|0|09/30/2013|0|0
|
17
|
+
H0AL05163|BROOKS, MO|I|2|REP|188145|0|55273.51|0|499658.59|632530.08|0|0|0|0|0|0|85045|AL|05||||||103100|0|09/30/2013|0|0
|
metadata
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fech-ftp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Derek Willis
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-07-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: fech
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: remote_table
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: american_date
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: sqlite3
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: sequel
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubyzip
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: activesupport
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
description: Retrieve and parse summary and detailed federal campaign finance data.
|
154
|
+
email:
|
155
|
+
- dwillis@gmail.com
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- ".gitignore"
|
161
|
+
- Gemfile
|
162
|
+
- LICENSE.txt
|
163
|
+
- README.md
|
164
|
+
- Rakefile
|
165
|
+
- fech-ftp.gemspec
|
166
|
+
- lib/fech-ftp.rb
|
167
|
+
- lib/fech-ftp/candidate.rb
|
168
|
+
- lib/fech-ftp/candidate_contribution.rb
|
169
|
+
- lib/fech-ftp/committee.rb
|
170
|
+
- lib/fech-ftp/committee_contribution.rb
|
171
|
+
- lib/fech-ftp/individual_contribution.rb
|
172
|
+
- lib/fech-ftp/table.rb
|
173
|
+
- lib/fech-ftp/table_methods.rb
|
174
|
+
- lib/fech-ftp/version.rb
|
175
|
+
- test/cm.txt
|
176
|
+
- test/cn.txt
|
177
|
+
- test/itcont.txt
|
178
|
+
- test/test_candidate.rb
|
179
|
+
- test/test_committee.rb
|
180
|
+
- test/test_individual.rb
|
181
|
+
- test/webk.txt
|
182
|
+
- test/webl.txt
|
183
|
+
homepage: ''
|
184
|
+
licenses:
|
185
|
+
- MIT
|
186
|
+
metadata: {}
|
187
|
+
post_install_message:
|
188
|
+
rdoc_options: []
|
189
|
+
require_paths:
|
190
|
+
- lib
|
191
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
192
|
+
requirements:
|
193
|
+
- - ">="
|
194
|
+
- !ruby/object:Gem::Version
|
195
|
+
version: '0'
|
196
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
197
|
+
requirements:
|
198
|
+
- - ">="
|
199
|
+
- !ruby/object:Gem::Version
|
200
|
+
version: '0'
|
201
|
+
requirements: []
|
202
|
+
rubyforge_project:
|
203
|
+
rubygems_version: 2.4.5
|
204
|
+
signing_key:
|
205
|
+
specification_version: 4
|
206
|
+
summary: A Ruby interface for FTP data from the Federal Election Commission.
|
207
|
+
test_files:
|
208
|
+
- test/cm.txt
|
209
|
+
- test/cn.txt
|
210
|
+
- test/itcont.txt
|
211
|
+
- test/test_candidate.rb
|
212
|
+
- test/test_committee.rb
|
213
|
+
- test/test_individual.rb
|
214
|
+
- test/webk.txt
|
215
|
+
- test/webl.txt
|