ifill 0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MzQwN2NkOGI2YTIzY2MyYWNjZjE2ZDFjYzM5YjdjODU3ZjBjYjA3OQ==
5
+ data.tar.gz: !binary |-
6
+ Mzc5OGEyZjBmMGMyYTZlYjI1MTlhZmZjMzViZjg0NWJmZTI1NjY4MQ==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ ZWFmOTMyNzVkZjE2YzI3M2E2YWQ2NDYxNWM0MjQ4NDExYmNlZmI2NzM3MGNi
10
+ ODBhMDU5MWFjMWI3OWUwM2IyMjhjZTUxZTE0ZmY2MWZiZTZhNTVmZTVhY2U3
11
+ ZTY4ZjkxMGMwNDIwN2ZlNTk5ZWI3Mzc5YjgyZTgzNzIzMzI4MDY=
12
+ data.tar.gz: !binary |-
13
+ ZGIzOGE4OTQ3MGZmODhjZjA4OGZhNjU3ODRkYTNkY2IxNzY0NDgyMTg1MmNk
14
+ YWUxOWE2NDEwZmRmODQ0NmZhM2JkYTBjYzZkZDVhNTk3MWFmNWU0YzBlMzg5
15
+ ZDk1MTkyNjdkNjA3ZmFhZTYzY2ZiOTNhNzQxMDk1ODY0ZDc3NTI=
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in presdocs.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,23 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ presdocs (0.5)
5
+ json
6
+ oj
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ json (1.7.7)
12
+ minitest (4.6.1)
13
+ oj (2.0.7)
14
+ rake (0.8.7)
15
+
16
+ PLATFORMS
17
+ ruby
18
+
19
+ DEPENDENCIES
20
+ bundler (>= 1.1.0)
21
+ minitest
22
+ presdocs!
23
+ rake (= 0.8.7)
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 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,51 @@
1
+ # Ifill: A Ruby wrapper for the Compilation of Presidential Documents
2
+
3
+ The White House releases a lot of stuff, and some of it is included in what's known as the [Compilation of Presidential Documents](http://www.gpo.gov/fdsys/browse/collection.action?collectionCode=CPD). This is a Ruby library for accessing details about those documents, including subjects, dates, locations and more.
4
+
5
+ Nearly every day, the White House releases one or more official publications, which may include presidential statements, announcements of nominations, press releases and schedule information. These are published by the Government Printing Office. Ifill wraps JSON endpoints exposed by GPO, which has created a [mobile application](http://m.gpo.gov/dcpd) for browsing and searching these documents. I owe a debt of gratitude to the government employees who made these endpoints available; your commitment to making public information more easily accessible is truly a public service.
6
+
7
+ Ifill is named for Gwen Ifill, a former New York Times White House correspondent.
8
+
9
+ The current version is 0.6.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'ifill'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install ifill
24
+
25
+ ## Usage
26
+
27
+ require 'rubygems'
28
+ require 'ifill'
29
+ include Ifill
30
+
31
+ @latest_docs = Document.latest
32
+
33
+ Please see [the documentation](http://dwillis.github.com/ifill/) for a more complete description of the library.
34
+
35
+ ## Tests
36
+
37
+ Ifill uses minitest and is tested under Ruby 1.9.3; to run the tests:
38
+
39
+ rake test
40
+
41
+ ## License
42
+
43
+ Ifill is licensed under the MIT License. See LICENSE.txt for more details.
44
+
45
+ ## Contributing
46
+
47
+ 1. Fork it
48
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
49
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
50
+ 4. Push to the branch (`git push origin my-new-feature`)
51
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.pattern = "test/test_*.rb"
6
+ end
data/ifill.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ifill/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "ifill"
8
+ gem.version = Ifill::VERSION
9
+ gem.authors = ["Derek Willis"]
10
+ gem.email = ["dwillis@gmail.com"]
11
+ gem.description = %q{Thin Ruby wrapper for the Compilation of Presidential Documents}
12
+ gem.summary = %q{Official publications of materials released by the White House Press Secretary}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.required_rubygems_version = ">= 1.3.6"
21
+ gem.rubyforge_project = "ifill"
22
+ gem.add_runtime_dependency "json"
23
+
24
+ gem.add_dependency "oj"
25
+
26
+ gem.add_development_dependency "rake", "0.8.7"
27
+ gem.add_development_dependency "bundler", ">= 1.1.0"
28
+ gem.add_development_dependency "minitest"
29
+
30
+ end
@@ -0,0 +1,29 @@
1
+ module Ifill
2
+ class Category
3
+
4
+ attr_reader :name, :count, :children
5
+
6
+ def initialize(params={})
7
+ params.each_pair do |k,v|
8
+ instance_variable_set("@#{k}", v)
9
+ end
10
+ end
11
+
12
+ def self.all
13
+ url = "http://m.gpo.gov/wscpd/mobilecpd/category.json"
14
+ results = Oj.load(open(url).read)
15
+ create_categories(results['navigatorResults']['Category'])
16
+ end
17
+
18
+ def self.create_categories(results)
19
+ cats = []
20
+ results.each do |result|
21
+ cats << self.new(:name => result['name'],
22
+ :count => result['count'],
23
+ :children => result['children'])
24
+ end
25
+ cats
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,127 @@
1
+ module Ifill
2
+ class Document
3
+
4
+ attr_reader :id, :location, :title, :source, :president, :date, :package_id, :lat, :lng, :subjects, :category, :notes, :fdsys_url, :html, :city, :state
5
+
6
+ def initialize(params={})
7
+ params.each_pair do |k,v|
8
+ instance_variable_set("@#{k}", v)
9
+ end
10
+ end
11
+
12
+ def add_attributes(params)
13
+ params.each_pair do |k,v|
14
+ instance_variable_set("@#{k}", v)
15
+ end
16
+ end
17
+
18
+ def detail
19
+ Document.detail(id)
20
+ end
21
+
22
+ def self.detail(package_id)
23
+ url = "http://m.gpo.gov/wscpd/mobilecpd/detailwgc/#{package_id}.json"
24
+ result = Oj.load(open(url).read)
25
+ create_document(result, nil, full=true)
26
+ end
27
+
28
+ def self.latest
29
+ url = "http://m.gpo.gov/wscpd/mobilecpd/home.json"
30
+ results = Oj.load(open(url).read)
31
+ create_from_search_results(results['searchResults'], nil)
32
+ end
33
+
34
+ def self.with_locations
35
+ url = "http://m.gpo.gov/wscpd/mobilecpd/location.json"
36
+ results = Oj.load(open(url).read)
37
+ create_from_search_results(results['searchResults'], results['coordinates'])
38
+ end
39
+
40
+ def self.city(city, state)
41
+ url = "http://m.gpo.gov/wscpd/mobilecpd/location/#{city}/#{state}.json"
42
+ results = Oj.load(open(url).read)
43
+ create_from_search_results(results['searchResults'], results['coordinates'])
44
+ end
45
+
46
+ def self.state(state)
47
+ url = "http://m.gpo.gov/wscpd/mobilecpd/location/#{state}.json"
48
+ results = Oj.load(open(url).read)
49
+ create_from_search_results(results['searchResults'], results['coordinates'])
50
+ end
51
+
52
+ def self.location_with_distance(lat, lng, distance)
53
+ url = "http://m.gpo.gov/wscpd/mobilecpd/location/#{lat}/#{lng}/#{distance}.json"
54
+ results = Oj.load(open(url).read)
55
+ create_from_search_results(results['searchResults'], results['coordinates'])
56
+ end
57
+
58
+ def self.date(date)
59
+ d = process_date(date)
60
+ url = "http://m.gpo.gov/wscpd/mobilecpd/date/#{d}.json"
61
+ results = Oj.load(open(url).read)
62
+ create_from_search_results(results['searchResults'], nil)
63
+ end
64
+
65
+ def self.date_range(start_date, end_date)
66
+ s = process_date(start_date)
67
+ e = process_date(end_date)
68
+ url = "http://m.gpo.gov/wscpd/mobilecpd/date/#{s}/#{e}.json"
69
+ results = Oj.load(open(url).read)
70
+ create_from_search_results(results['searchResults'], nil)
71
+ end
72
+
73
+ def self.category(category)
74
+ url = "http://m.gpo.gov/wscpd/mobilecpd/category/#{category}.json"
75
+ results = Oj.load(open(url).read)
76
+ create_from_search_results(results['searchResults'], nil)
77
+ end
78
+
79
+ def self.process_date(date)
80
+ begin
81
+ if date.is_a?(Date)
82
+ d = date.strftime("%-m-%-d-%Y")
83
+ else
84
+ d = Date.strptime(date, '%m/%d/%Y').strftime("%-m-%-d-%Y")
85
+ end
86
+ rescue
87
+ raise "Dates must be Ruby Date objects or a Date string such as '2/14/2013'"
88
+ end
89
+ end
90
+
91
+ def self.create_from_search_results(results, coordinates)
92
+ docs = []
93
+ results.each do |result|
94
+ docs << create_document(result, coordinates)
95
+ end
96
+ docs
97
+ end
98
+
99
+ def self.create_document(result, coordinates, full=false)
100
+ if full
101
+ detail = result
102
+ result = result['searchResult']
103
+ end
104
+ city, state = result['location'].split(', ') if result['location']
105
+ if coordinates
106
+ locations = coordinates.map{|l| {"state" => l['state'], "city" => l['city'], "lat" => l["lat"], "lng" => l["lang"]}}.uniq
107
+ lat = locations.detect{|l| l['city'] == city && l['state'] == state}['lat']
108
+ lng = locations.detect{|l| l['city'] == city && l['state'] == state}['lng']
109
+ end
110
+ doc = self.new(:id => result['packageId'],
111
+ :city => city,
112
+ :state => state,
113
+ :lat => lat,
114
+ :lng => lng,
115
+ :title => result['line1'],
116
+ :source => result['line2'],
117
+ :president => result['president'],
118
+ :date => Date.parse(result['eventDate']))
119
+
120
+ if full
121
+ h = {:category => detail['category'], :notes => detail['notes'], :subjects => detail['subject'].map{|s| s.strip}.reject!(&:empty?), :fdsys_url => detail['fdsysUrl'], :html => detail['fullText']}
122
+ doc.add_attributes(h)
123
+ end
124
+ doc
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,3 @@
1
+ module Ifill
2
+ VERSION = "0.6"
3
+ end
data/lib/ifill.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'open-uri'
2
+ require 'oj'
3
+
4
+ %w(document.rb category.rb version.rb).each do |f|
5
+ require File.join(File.dirname(__FILE__), 'ifill/', f)
6
+ end
@@ -0,0 +1,47 @@
1
+ require 'rubygems'
2
+ require 'ifill'
3
+ include Ifill
4
+ require 'minitest/autorun'
5
+
6
+ class TestDocument < MiniTest::Unit::TestCase
7
+
8
+ def setup
9
+ @latest = Document.latest
10
+ @categories = Category.all
11
+ @locations = Document.with_locations
12
+ @doc = Document.detail('DCPD-201300104')
13
+ @date = Document.date('2/14/2013')
14
+ end
15
+
16
+ def test_that_there_are_five_latest_docs
17
+ assert_equal 5, @latest.size
18
+ end
19
+
20
+ def test_that_latest_docs_dont_have_coords
21
+ assert_nil @latest.first.lat
22
+ end
23
+
24
+ def test_that_categories_have_a_positive_count
25
+ assert_operator @categories.count, :>=, 0
26
+ end
27
+
28
+ def test_that_location_docs_have_lat_and_lng
29
+ assert @locations.last.lat
30
+ assert @locations.first.lng
31
+ end
32
+
33
+ def test_that_document_detail_has_an_fdsys_url
34
+ assert_equal "http://www.gpo.gov/fdsys/pkg/DCPD-201300104/html/DCPD-201300104.htm", @doc.fdsys_url
35
+ end
36
+
37
+ def test_that_document_date_results_are_from_same_date
38
+ assert_equal Date.strptime('2/14/2013', '%m/%d/%Y'), @date.map{|d| d.date}.uniq.first
39
+ end
40
+
41
+ def test_that_date_range_raises_error_for_bad_dates
42
+ assert_raises RuntimeError do
43
+ @range = Document.date_range('2/14/2013', '235')
44
+ end
45
+ end
46
+
47
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ifill
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.6'
5
+ platform: ruby
6
+ authors:
7
+ - Derek Willis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-06-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: oj
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
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: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.8.7
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.8.7
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.1.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: 1.1.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Thin Ruby wrapper for the Compilation of Presidential Documents
84
+ email:
85
+ - dwillis@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - .gitignore
91
+ - Gemfile
92
+ - Gemfile.lock
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - ifill.gemspec
97
+ - lib/ifill.rb
98
+ - lib/ifill/category.rb
99
+ - lib/ifill/document.rb
100
+ - lib/ifill/version.rb
101
+ - test/test_document.rb
102
+ homepage: ''
103
+ licenses: []
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ! '>='
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: 1.3.6
119
+ requirements: []
120
+ rubyforge_project: ifill
121
+ rubygems_version: 2.0.3
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Official publications of materials released by the White House Press Secretary
125
+ test_files:
126
+ - test/test_document.rb