federal_register 0.5.1 → 0.6.0
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/.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
|