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.
Files changed (50) hide show
  1. data/.rubocop.yml +286 -0
  2. data/Gemfile +3 -4
  3. data/Gemfile.lock +82 -22
  4. data/README.md +6 -6
  5. data/Rakefile +5 -5
  6. data/VERSION +1 -1
  7. data/federal_register.gemspec +49 -19
  8. data/lib/federal_register.rb +41 -0
  9. data/lib/federal_register/agency.rb +45 -9
  10. data/lib/federal_register/article.rb +2 -106
  11. data/lib/federal_register/base.rb +52 -3
  12. data/lib/federal_register/client.rb +3 -3
  13. data/lib/federal_register/document.rb +113 -0
  14. data/lib/federal_register/document_image.rb +17 -0
  15. data/lib/federal_register/facet.rb +21 -0
  16. data/lib/federal_register/facet/agency.rb +5 -0
  17. data/lib/federal_register/facet/document.rb +2 -0
  18. data/lib/federal_register/facet/document/agency.rb +5 -0
  19. data/lib/federal_register/facet/document/daily.rb +5 -0
  20. data/lib/federal_register/facet/document/frequency.rb +12 -0
  21. data/lib/federal_register/facet/document/monthly.rb +5 -0
  22. data/lib/federal_register/facet/document/quarterly.rb +5 -0
  23. data/lib/federal_register/facet/document/section.rb +5 -0
  24. data/lib/federal_register/facet/document/topic.rb +5 -0
  25. data/lib/federal_register/facet/document/type.rb +5 -0
  26. data/lib/federal_register/facet/document/weekly.rb +5 -0
  27. data/lib/federal_register/facet/document/yearly.rb +5 -0
  28. data/lib/federal_register/facet/presidential_document_type.rb +6 -0
  29. data/lib/federal_register/facet/public_inspection_document.rb +2 -0
  30. data/lib/federal_register/facet/public_inspection_document/agencies.rb +5 -0
  31. data/lib/federal_register/facet/public_inspection_document/agency.rb +5 -0
  32. data/lib/federal_register/facet/public_inspection_document/type.rb +5 -0
  33. data/lib/federal_register/facet/public_inspection_issue.rb +36 -0
  34. data/lib/federal_register/facet/public_inspection_issue/daily.rb +11 -0
  35. data/lib/federal_register/facet/public_inspection_issue/daily_filing.rb +6 -0
  36. data/lib/federal_register/facet/public_inspection_issue/type.rb +11 -0
  37. data/lib/federal_register/facet/public_inspection_issue/type_filing.rb +22 -0
  38. data/lib/federal_register/facet/topic.rb +5 -0
  39. data/lib/federal_register/facet_result_set.rb +25 -0
  40. data/lib/federal_register/highlighted_document.rb +42 -0
  41. data/lib/federal_register/public_inspection_document.rb +21 -7
  42. data/lib/federal_register/public_inspection_issue_result_set.rb +10 -0
  43. data/lib/federal_register/result_set.rb +5 -5
  44. data/lib/federal_register/section.rb +26 -0
  45. data/lib/federal_register/suggested_search.rb +26 -0
  46. data/lib/federal_register/topic.rb +13 -0
  47. data/spec/{article_spec.rb → document_spec.rb} +20 -28
  48. data/spec/public_inspection_document_spec.rb +5 -6
  49. data/spec/result_set_spec.rb +4 -4
  50. 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,5 @@
1
+ class FederalRegister::Facet::Agency < FederalRegister::Facet
2
+ def self.url
3
+ '/documents/facets/agency'
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ class FederalRegister::Facet::Document < FederalRegister::Facet
2
+ end
@@ -0,0 +1,5 @@
1
+ class FederalRegister::Facet::Document::Agency < FederalRegister::Facet::Document
2
+ def self.url
3
+ '/documents/facets/agency'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class FederalRegister::Facet::Document::Daily < FederalRegister::Facet::Document::Frequency
2
+ def self.url
3
+ '/documents/facets/daily'
4
+ end
5
+ 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,5 @@
1
+ class FederalRegister::Facet::Document::Monthly < FederalRegister::Facet::Document::Frequency
2
+ def self.url
3
+ '/documents/facets/monthly'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class FederalRegister::Facet::Document::Quarterly < FederalRegister::Facet::Document::Frequency
2
+ def self.url
3
+ '/documents/facets/quarterly'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class FederalRegister::Facet::Document::Section < FederalRegister::Facet::Document
2
+ def self.url
3
+ '/documents/facets/section'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class FederalRegister::Facet::Document::Topic < FederalRegister::Facet::Document
2
+ def self.url
3
+ '/documents/facets/topic'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class FederalRegister::Facet::Document::Type < FederalRegister::Facet::Document
2
+ def self.url
3
+ '/documents/facets/type'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class FederalRegister::Facet::Document::Weekly < FederalRegister::Facet::Document::Frequency
2
+ def self.url
3
+ '/documents/facets/weekly'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class FederalRegister::Facet::Document::Yearly < FederalRegister::Facet::Document::Frequency
2
+ def self.url
3
+ '/documents/facets/yearly'
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class FederalRegister::Facet::PresidentialDocumentType < FederalRegister::Facet
2
+ def self.url
3
+ '/documents/facets/subtype'
4
+ end
5
+ end
6
+
@@ -0,0 +1,2 @@
1
+ class FederalRegister::Facet::PublicInspectionDocument < FederalRegister::Facet
2
+ end
@@ -0,0 +1,5 @@
1
+ class FederalRegister::Facet::PublicInspectionDocument::Agencies < FederalRegister::Facet::PublicInspectionDocument
2
+ def self.url
3
+ '/public-inspection-documents/facets/agencies'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class FederalRegister::Facet::PublicInspectionDocument::Agency < FederalRegister::Facet::PublicInspectionDocument
2
+ def self.url
3
+ '/public-inspection-documents/facets/agency'
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class FederalRegister::Facet::PublicInspectionDocument::Type < FederalRegister::Facet::PublicInspectionDocument
2
+ def self.url
3
+ '/public-inspection-documents/facets/type'
4
+ end
5
+ 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,6 @@
1
+ class FederalRegister::Facet::PublicInspectionIssue::DailyFiling < FederalRegister::Facet::PublicInspectionIssue
2
+ add_attribute :agencies, :documents
3
+
4
+ add_attribute :last_updated_at,
5
+ :type => :datetime
6
+ 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,5 @@
1
+ class FederalRegister::Facet::Topic < FederalRegister::Facet
2
+ def self.url
3
+ '/documents/facets/topic'
4
+ end
5
+ 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