federal_register 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rubocop.yml +286 -0
- data/Gemfile +3 -4
- data/Gemfile.lock +82 -22
- data/README.md +6 -6
- data/Rakefile +5 -5
- data/VERSION +1 -1
- data/federal_register.gemspec +49 -19
- data/lib/federal_register.rb +41 -0
- data/lib/federal_register/agency.rb +45 -9
- data/lib/federal_register/article.rb +2 -106
- data/lib/federal_register/base.rb +52 -3
- data/lib/federal_register/client.rb +3 -3
- data/lib/federal_register/document.rb +113 -0
- data/lib/federal_register/document_image.rb +17 -0
- data/lib/federal_register/facet.rb +21 -0
- data/lib/federal_register/facet/agency.rb +5 -0
- data/lib/federal_register/facet/document.rb +2 -0
- data/lib/federal_register/facet/document/agency.rb +5 -0
- data/lib/federal_register/facet/document/daily.rb +5 -0
- data/lib/federal_register/facet/document/frequency.rb +12 -0
- data/lib/federal_register/facet/document/monthly.rb +5 -0
- data/lib/federal_register/facet/document/quarterly.rb +5 -0
- data/lib/federal_register/facet/document/section.rb +5 -0
- data/lib/federal_register/facet/document/topic.rb +5 -0
- data/lib/federal_register/facet/document/type.rb +5 -0
- data/lib/federal_register/facet/document/weekly.rb +5 -0
- data/lib/federal_register/facet/document/yearly.rb +5 -0
- data/lib/federal_register/facet/presidential_document_type.rb +6 -0
- data/lib/federal_register/facet/public_inspection_document.rb +2 -0
- data/lib/federal_register/facet/public_inspection_document/agencies.rb +5 -0
- data/lib/federal_register/facet/public_inspection_document/agency.rb +5 -0
- data/lib/federal_register/facet/public_inspection_document/type.rb +5 -0
- data/lib/federal_register/facet/public_inspection_issue.rb +36 -0
- data/lib/federal_register/facet/public_inspection_issue/daily.rb +11 -0
- data/lib/federal_register/facet/public_inspection_issue/daily_filing.rb +6 -0
- data/lib/federal_register/facet/public_inspection_issue/type.rb +11 -0
- data/lib/federal_register/facet/public_inspection_issue/type_filing.rb +22 -0
- data/lib/federal_register/facet/topic.rb +5 -0
- data/lib/federal_register/facet_result_set.rb +25 -0
- data/lib/federal_register/highlighted_document.rb +42 -0
- data/lib/federal_register/public_inspection_document.rb +21 -7
- data/lib/federal_register/public_inspection_issue_result_set.rb +10 -0
- data/lib/federal_register/result_set.rb +5 -5
- data/lib/federal_register/section.rb +26 -0
- data/lib/federal_register/suggested_search.rb +26 -0
- data/lib/federal_register/topic.rb +13 -0
- data/spec/{article_spec.rb → document_spec.rb} +20 -28
- data/spec/public_inspection_document_spec.rb +5 -6
- data/spec/result_set_spec.rb +4 -4
- metadata +99 -39
@@ -1,6 +1,6 @@
|
|
1
1
|
class FederalRegister::Client
|
2
2
|
include HTTParty
|
3
|
-
|
3
|
+
|
4
4
|
class ResponseError < HTTParty::ResponseError
|
5
5
|
def message
|
6
6
|
response.body
|
@@ -16,10 +16,10 @@ class FederalRegister::Client
|
|
16
16
|
class ServerError < ResponseError; end
|
17
17
|
|
18
18
|
base_uri 'https://www.federalregister.gov/api/v1'
|
19
|
-
|
19
|
+
|
20
20
|
def self.get(url, *options)
|
21
21
|
response = super
|
22
|
-
|
22
|
+
|
23
23
|
case response.code
|
24
24
|
when 200
|
25
25
|
response
|
@@ -0,0 +1,113 @@
|
|
1
|
+
class FederalRegister::Document < FederalRegister::Base
|
2
|
+
extend FederalRegister::Utilities
|
3
|
+
|
4
|
+
add_attribute :abstract,
|
5
|
+
:abstract_html_url,
|
6
|
+
:action,
|
7
|
+
:agencies,
|
8
|
+
:agency_names,
|
9
|
+
:body_html_url,
|
10
|
+
:cfr_references,
|
11
|
+
:citation,
|
12
|
+
:comment_url,
|
13
|
+
:corrections,
|
14
|
+
:correction_of,
|
15
|
+
:dates,
|
16
|
+
:docket_id,
|
17
|
+
:docket_ids,
|
18
|
+
:document_number,
|
19
|
+
:end_page,
|
20
|
+
:excerpts,
|
21
|
+
:executive_order_notes,
|
22
|
+
:executive_order_number,
|
23
|
+
:full_text_xml_url,
|
24
|
+
:html_url,
|
25
|
+
:images,
|
26
|
+
:json_url,
|
27
|
+
:mods_url,
|
28
|
+
:pdf_url,
|
29
|
+
:president,
|
30
|
+
:public_inspection_pdf_url,
|
31
|
+
:regulation_id_number_info,
|
32
|
+
:regulation_id_numbers,
|
33
|
+
:regulations_dot_gov_info,
|
34
|
+
:regulations_dot_gov_url,
|
35
|
+
:significant,
|
36
|
+
:start_page,
|
37
|
+
:subtype,
|
38
|
+
:raw_text_url,
|
39
|
+
:title,
|
40
|
+
:toc_subject,
|
41
|
+
:toc_doc,
|
42
|
+
:type,
|
43
|
+
:volume
|
44
|
+
|
45
|
+
add_attribute :comments_close_on,
|
46
|
+
:effective_on,
|
47
|
+
:publication_date,
|
48
|
+
:signing_date,
|
49
|
+
:type => :date
|
50
|
+
|
51
|
+
def self.search(args)
|
52
|
+
FederalRegister::ResultSet.fetch("/documents.json", :query => args, :result_class => self)
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.search_metadata(args)
|
56
|
+
FederalRegister::ResultSet.fetch("/documents.json", :query => args.merge(:metadata_only => '1'), :result_class => self)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.find(document_number, options={})
|
60
|
+
if options[:fields].present?
|
61
|
+
attributes = get("/documents/#{document_number}.json", :query => {:fields => options[:fields]})
|
62
|
+
new(attributes)
|
63
|
+
else
|
64
|
+
attributes = get("/documents/#{document_number}.json")
|
65
|
+
new(attributes, :full => true)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.find_all(*args)
|
70
|
+
options, document_numbers = extract_options(args)
|
71
|
+
|
72
|
+
fetch_options = {:result_class => self}
|
73
|
+
fetch_options.merge!(:query => {:fields => options[:fields]}) if options[:fields]
|
74
|
+
|
75
|
+
document_numbers = document_numbers.flatten
|
76
|
+
|
77
|
+
#TODO: fix this gross hack to ensure that find_all with a single document number
|
78
|
+
# is returned in the same way multiple document numbers are
|
79
|
+
if document_numbers.size == 1
|
80
|
+
document_numbers << " "
|
81
|
+
end
|
82
|
+
|
83
|
+
result_set = FederalRegister::ResultSet.fetch("/documents/#{document_numbers.join(',').strip}.json", fetch_options)
|
84
|
+
end
|
85
|
+
|
86
|
+
def agencies
|
87
|
+
attributes["agencies"].map do |attr|
|
88
|
+
FederalRegister::Agency.new(attr)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
%w(full_text_xml abstract_html body_html raw_text mods).each do |file_type|
|
93
|
+
define_method file_type do
|
94
|
+
begin
|
95
|
+
self.class.get(send("#{file_type}_url")).body
|
96
|
+
rescue FederalRegister::Client::RecordNotFound
|
97
|
+
nil
|
98
|
+
rescue
|
99
|
+
raise send("#{file_type}_url").inspect
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def images
|
105
|
+
if attributes["images"]
|
106
|
+
attributes["images"].map do |attributes|
|
107
|
+
FederalRegister::DocumentImage.new(attributes)
|
108
|
+
end
|
109
|
+
else
|
110
|
+
[]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class FederalRegister::DocumentImage < FederalRegister::Document
|
2
|
+
def identifier
|
3
|
+
attributes[0]
|
4
|
+
end
|
5
|
+
|
6
|
+
def sizes
|
7
|
+
attributes[1].keys
|
8
|
+
end
|
9
|
+
|
10
|
+
def url_for(size)
|
11
|
+
attributes[1][size]
|
12
|
+
end
|
13
|
+
|
14
|
+
def default_url
|
15
|
+
sizes.include?('original_png') ? url_for('original_png') : url_for('original')
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class FederalRegister::Facet < FederalRegister::Base
|
2
|
+
extend FederalRegister::Utilities
|
3
|
+
|
4
|
+
attr_reader :result_set
|
5
|
+
|
6
|
+
add_attribute :count,
|
7
|
+
:name,
|
8
|
+
:slug
|
9
|
+
|
10
|
+
def self.search(args={})
|
11
|
+
FederalRegister::FacetResultSet.fetch(
|
12
|
+
url, :query => args, :result_class => self
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(attributes={}, options={})
|
17
|
+
@result_set = options.delete(:result_set)
|
18
|
+
|
19
|
+
super(attributes, options)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class FederalRegister::Facet::Document::Frequency < FederalRegister::Facet::Document
|
2
|
+
def self.chart_url(args={})
|
3
|
+
uri = [base_uri, url, '.png']
|
4
|
+
|
5
|
+
if args.present?
|
6
|
+
uri << '?'
|
7
|
+
uri << HTTParty::HashConversions.to_params(args)
|
8
|
+
end
|
9
|
+
|
10
|
+
uri.join('')
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class FederalRegister::Facet::PublicInspectionIssue < FederalRegister::Base
|
2
|
+
add_attribute :slug
|
3
|
+
attr_reader :conditions
|
4
|
+
|
5
|
+
def initialize(attributes, options = {})
|
6
|
+
@conditions = options[:query] || {}
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def special_filings
|
11
|
+
@special_filings ||= filing_class.new(
|
12
|
+
attributes['special_filings'],
|
13
|
+
conditions.deep_merge({
|
14
|
+
conditions: {special_filing: 1}
|
15
|
+
})
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
def regular_filings
|
20
|
+
@regular_filings ||= filing_class.new(
|
21
|
+
attributes['regular_filings'],
|
22
|
+
conditions.deep_merge({
|
23
|
+
conditions: {special_filing: 0}
|
24
|
+
})
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.search(args={})
|
29
|
+
response = get(url, query: args)
|
30
|
+
|
31
|
+
response.map do |slug, attributes|
|
32
|
+
attributes['slug'] = slug
|
33
|
+
new(attributes, query: args)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class FederalRegister::Facet::PublicInspectionIssue::Daily < FederalRegister::Facet::PublicInspectionIssue
|
2
|
+
def self.url
|
3
|
+
'/public-inspection-issues/facets/daily'
|
4
|
+
end
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def filing_class
|
9
|
+
FederalRegister::Facet::PublicInspectionIssue::DailyFiling
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class FederalRegister::Facet::PublicInspectionIssue::Type < FederalRegister::Facet::PublicInspectionIssue
|
2
|
+
def self.url
|
3
|
+
'/public-inspection-issues/facets/type'
|
4
|
+
end
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def filing_class
|
9
|
+
FederalRegister::Facet::PublicInspectionIssue::TypeFiling
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class FederalRegister::Facet::PublicInspectionIssue::TypeFiling < FederalRegister::Facet::PublicInspectionIssue
|
2
|
+
attr_reader :document_types, :search_conditions
|
3
|
+
|
4
|
+
def initialize(attributes, conditions, options={})
|
5
|
+
@search_conditions = conditions
|
6
|
+
@document_types = attributes.map{|k,v| DocumentTypeFacet.new(k, v, @search_conditions)}
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
class DocumentTypeFacet
|
12
|
+
attr_reader :count, :name, :search_conditions
|
13
|
+
|
14
|
+
def initialize(type, attributes, search_conditions)
|
15
|
+
@count = attributes['count']
|
16
|
+
@name = attributes['name']
|
17
|
+
@search_conditions = search_conditions.deep_merge({
|
18
|
+
conditions: {type: type}
|
19
|
+
})
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class FederalRegister::FacetResultSet < FederalRegister::Client
|
2
|
+
include Enumerable
|
3
|
+
|
4
|
+
attr_reader :conditions, :results
|
5
|
+
|
6
|
+
def initialize(attributes, result_class, options={})
|
7
|
+
@result_class = result_class
|
8
|
+
@conditions = options[:query] || {}
|
9
|
+
|
10
|
+
@results = (attributes || {}).map do |slug, attributes|
|
11
|
+
attributes["slug"] = slug
|
12
|
+
@result_class.new(attributes, options.merge(:result_set => self) )
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.fetch(url, options = {})
|
17
|
+
result_class = options.delete(:result_class)
|
18
|
+
response = get(url, options)
|
19
|
+
new(response, result_class, options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def each
|
23
|
+
@results.each {|result| yield result }
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class FederalRegister::HighlightedDocument < FederalRegister::Base
|
2
|
+
class InvalidPhotoSize < StandardError; end
|
3
|
+
|
4
|
+
add_attribute :curated_abstract,
|
5
|
+
:curated_title,
|
6
|
+
:document_number,
|
7
|
+
:html_url,
|
8
|
+
:photo
|
9
|
+
|
10
|
+
VALID_PHOTO_SIZES = [
|
11
|
+
'full_size',
|
12
|
+
'homepage',
|
13
|
+
'large',
|
14
|
+
'medium',
|
15
|
+
'navigation',
|
16
|
+
'small'
|
17
|
+
]
|
18
|
+
|
19
|
+
def photo_url(size)
|
20
|
+
unless VALID_PHOTO_SIZES.include?(size)
|
21
|
+
raise InvalidPhotoSize,
|
22
|
+
"valid photo sizes are #{VALID_PHOTO_SIZES.join(', ')}"
|
23
|
+
end
|
24
|
+
|
25
|
+
if attributes['photo']
|
26
|
+
attributes['photo']['urls'][size]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def photo_credit
|
31
|
+
@credit ||= PhotoCredit.new(attributes['photo']['credit']) if attributes['photo']
|
32
|
+
end
|
33
|
+
|
34
|
+
class PhotoCredit
|
35
|
+
attr_reader :name, :url
|
36
|
+
|
37
|
+
def initialize(attributes)
|
38
|
+
@name = attributes['name']
|
39
|
+
@url = attributes['url']
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|