ecfr 1.0.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.
- checksums.yaml +7 -0
- data/.circleci/config.yml +11 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rspec_parallel +4 -0
- data/.rubocop.yml +28 -0
- data/.yardopts +3 -0
- data/CHANGELOG.md +6 -0
- data/Dockerfile +6 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +138 -0
- data/LICENSE.txt +21 -0
- data/README.md +133 -0
- data/Rakefile +12 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/ecfr.gemspec +74 -0
- data/lib/ecfr/admin_service/agency/hierarchy.rb +27 -0
- data/lib/ecfr/admin_service/agency.rb +34 -0
- data/lib/ecfr/admin_service/api_documentation.rb +7 -0
- data/lib/ecfr/admin_service/base.rb +26 -0
- data/lib/ecfr/admin_service/build.rb +38 -0
- data/lib/ecfr/admin_service/ecfr_correction/cfr_reference.rb +17 -0
- data/lib/ecfr/admin_service/ecfr_correction.rb +78 -0
- data/lib/ecfr/admin_service/editorial_note/hierarchy.rb +19 -0
- data/lib/ecfr/admin_service/editorial_note.rb +40 -0
- data/lib/ecfr/admin_service/ibr_cfr_range/address.rb +17 -0
- data/lib/ecfr/admin_service/ibr_cfr_range/organization.rb +28 -0
- data/lib/ecfr/admin_service/ibr_cfr_range.rb +67 -0
- data/lib/ecfr/admin_service/issue/change.rb +19 -0
- data/lib/ecfr/admin_service/issue.rb +86 -0
- data/lib/ecfr/admin_service/site_notification.rb +34 -0
- data/lib/ecfr/admin_service/status.rb +7 -0
- data/lib/ecfr/attribute_caster.rb +72 -0
- data/lib/ecfr/attribute_method_definition.rb +92 -0
- data/lib/ecfr/base.rb +71 -0
- data/lib/ecfr/client.rb +318 -0
- data/lib/ecfr/common/hierarchy.rb +35 -0
- data/lib/ecfr/configuration.rb +58 -0
- data/lib/ecfr/constants.rb +21 -0
- data/lib/ecfr/default_documentation_setup.rb +39 -0
- data/lib/ecfr/default_status_setup.rb +46 -0
- data/lib/ecfr/diff_service/base.rb +17 -0
- data/lib/ecfr/diff_service/status.rb +34 -0
- data/lib/ecfr/extensible.rb +45 -0
- data/lib/ecfr/facet_attribute_method_definition.rb +47 -0
- data/lib/ecfr/faraday/user_agent/middleware.rb +14 -0
- data/lib/ecfr/ofr_profile_service/base.rb +20 -0
- data/lib/ecfr/ofr_profile_service/status.rb +7 -0
- data/lib/ecfr/parallel_client.rb +33 -0
- data/lib/ecfr/prince_xml_service/base.rb +17 -0
- data/lib/ecfr/prince_xml_service/pdf.rb +31 -0
- data/lib/ecfr/renderer_service/base.rb +31 -0
- data/lib/ecfr/renderer_service/content.rb +34 -0
- data/lib/ecfr/renderer_service/diff.rb +31 -0
- data/lib/ecfr/renderer_service/origin.rb +56 -0
- data/lib/ecfr/renderer_service/status.rb +7 -0
- data/lib/ecfr/request_representation.rb +12 -0
- data/lib/ecfr/search_service/api_documentation.rb +7 -0
- data/lib/ecfr/search_service/base.rb +23 -0
- data/lib/ecfr/search_service/content_version/count.rb +33 -0
- data/lib/ecfr/search_service/content_version/hierarchical_count.rb +17 -0
- data/lib/ecfr/search_service/content_version/hierarchical_count_node.rb +30 -0
- data/lib/ecfr/search_service/content_version/hierarchichal_result.rb +42 -0
- data/lib/ecfr/search_service/content_version/result.rb +110 -0
- data/lib/ecfr/search_service/content_version/suggestion.rb +76 -0
- data/lib/ecfr/search_service/content_version/summary.rb +27 -0
- data/lib/ecfr/search_service/content_version.rb +85 -0
- data/lib/ecfr/search_service/date_facet.rb +19 -0
- data/lib/ecfr/search_service/facet_base.rb +55 -0
- data/lib/ecfr/search_service/status.rb +7 -0
- data/lib/ecfr/search_service/title_facet.rb +18 -0
- data/lib/ecfr/subscriptions_service/base.rb +19 -0
- data/lib/ecfr/subscriptions_service/status.rb +7 -0
- data/lib/ecfr/subscriptions_service/subscription.rb +97 -0
- data/lib/ecfr/testing/extensions/admin_service/ecfr_correction_extensions.rb +13 -0
- data/lib/ecfr/testing/extensions/admin_service/issue_extensions.rb +13 -0
- data/lib/ecfr/testing/extensions/renderer_service/origin_extensions.rb +13 -0
- data/lib/ecfr/testing/extensions/search_service/content_version_result_extensions.rb +16 -0
- data/lib/ecfr/testing/extensions/search_service/date_facet_extensions.rb +13 -0
- data/lib/ecfr/testing/extensions/versioner_service/ancestors_extensions.rb +20 -0
- data/lib/ecfr/testing/extensions/versioner_service/title_extenstions.rb +16 -0
- data/lib/ecfr/testing/factories/admin_service/cfr_reference_factory.rb +14 -0
- data/lib/ecfr/testing/factories/admin_service/ecfr_correction_factory.rb +31 -0
- data/lib/ecfr/testing/factories/admin_service/issue_change_factory.rb +12 -0
- data/lib/ecfr/testing/factories/admin_service/issue_factory.rb +21 -0
- data/lib/ecfr/testing/factories/common/hierarchy_factory.rb +36 -0
- data/lib/ecfr/testing/factories/renderer_service/origin_factory.rb +32 -0
- data/lib/ecfr/testing/factories/search_service/content_version_count_factory.rb +20 -0
- data/lib/ecfr/testing/factories/search_service/content_version_result_factory.rb +76 -0
- data/lib/ecfr/testing/factories/search_service/date_facet_factory.rb +12 -0
- data/lib/ecfr/testing/factories/versioner_service/ancestors_factory.rb +26 -0
- data/lib/ecfr/testing/factories/versioner_service/metadata_node_info_factory.rb +15 -0
- data/lib/ecfr/testing/factories/versioner_service/node_summary_factory.rb +16 -0
- data/lib/ecfr/testing/factories/versioner_service/structure_factory.rb +57 -0
- data/lib/ecfr/testing/factories/versioner_service/title_factory.rb +36 -0
- data/lib/ecfr/testing/factory_bot_helpers/content_version.rb +38 -0
- data/lib/ecfr/testing/factory_bot_helpers/ecfr_gem_initialize_helpers.rb +51 -0
- data/lib/ecfr/testing/helpers/response_helper.rb +5 -0
- data/lib/ecfr/testing/strategies/ecfr_attribute_hash_strategy.rb +37 -0
- data/lib/ecfr/testing.rb +28 -0
- data/lib/ecfr/version.rb +5 -0
- data/lib/ecfr/versioner_service/ancestors/metadata_node_info.rb +22 -0
- data/lib/ecfr/versioner_service/ancestors/node_summary.rb +54 -0
- data/lib/ecfr/versioner_service/ancestors.rb +152 -0
- data/lib/ecfr/versioner_service/api_documentation.rb +7 -0
- data/lib/ecfr/versioner_service/base.rb +24 -0
- data/lib/ecfr/versioner_service/status.rb +7 -0
- data/lib/ecfr/versioner_service/structure.rb +120 -0
- data/lib/ecfr/versioner_service/title.rb +78 -0
- data/lib/ecfr/versioner_service/xml_content.rb +59 -0
- data/lib/ecfr.rb +90 -0
- data/lib/yard/attribute_handler.rb +87 -0
- data/lib/yard/metadata_handler.rb +87 -0
- metadata +389 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module Ecfr
|
|
2
|
+
module SearchService
|
|
3
|
+
class ContentVersion < Base
|
|
4
|
+
require_relative "./content_version/count"
|
|
5
|
+
require_relative "./content_version/hierarchichal_result"
|
|
6
|
+
require_relative "./content_version/result"
|
|
7
|
+
require_relative "./content_version/suggestion"
|
|
8
|
+
require_relative "./content_version/summary"
|
|
9
|
+
|
|
10
|
+
#
|
|
11
|
+
# Metadata about the number of matching items
|
|
12
|
+
#
|
|
13
|
+
# @param [<Hash>] args valid search arguments, see {Result.find}
|
|
14
|
+
#
|
|
15
|
+
# @return [<Count>] count metadata
|
|
16
|
+
#
|
|
17
|
+
def self.count(args)
|
|
18
|
+
lookup(Ecfr::SearchService::ContentVersion::Count).find(args)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
#
|
|
22
|
+
# Search results in a hierarchical format with score data
|
|
23
|
+
#
|
|
24
|
+
# @param [<Hash>] args valid search arguments, see {Result.find}
|
|
25
|
+
#
|
|
26
|
+
# @return [<HierarchicalSearchCount>] hierarchical search results
|
|
27
|
+
#
|
|
28
|
+
def self.hierarchical_search(args)
|
|
29
|
+
lookup(
|
|
30
|
+
Ecfr::SearchService::ContentVersion::HierarchicalResult
|
|
31
|
+
).find(args)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# Search results with excerpts and score data
|
|
36
|
+
#
|
|
37
|
+
# @param [<Hash>] args valid search arguments, see {Result.find}
|
|
38
|
+
#
|
|
39
|
+
# @return [<Result>] results of a search
|
|
40
|
+
#
|
|
41
|
+
def self.search(args)
|
|
42
|
+
lookup(Ecfr::SearchService::ContentVersion::Result).find(args)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
#
|
|
46
|
+
# Suggestions based on the content of a search.
|
|
47
|
+
# Currently suggests direct link to a portion of the CFR when
|
|
48
|
+
# a CFR citation is detected as part of the `query`
|
|
49
|
+
#
|
|
50
|
+
# @param [<Hash>] args valid search arguments, see {Result.find}
|
|
51
|
+
#
|
|
52
|
+
# @return [<Suggestion>] search suggestions
|
|
53
|
+
#
|
|
54
|
+
def self.suggestions(args)
|
|
55
|
+
lookup(Ecfr::SearchService::ContentVersion::Suggestion).find(args)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
#
|
|
59
|
+
# Summary of the search based on the arguments provided
|
|
60
|
+
# - summary only makes use of the :hierarchy and :query
|
|
61
|
+
# args currenly
|
|
62
|
+
#
|
|
63
|
+
# @param [<Hash>] args valid search arguments, see {Result.find}
|
|
64
|
+
#
|
|
65
|
+
# @return [<Summary>] A descriptive summary of the search
|
|
66
|
+
#
|
|
67
|
+
def self.summary(args)
|
|
68
|
+
lookup(Ecfr::SearchService::ContentVersion::Summary).find(args)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
#
|
|
72
|
+
# Support inheritance by looking up class. See
|
|
73
|
+
# Ecfr::Extensible for details.
|
|
74
|
+
#
|
|
75
|
+
def self.lookup(klass)
|
|
76
|
+
if const_defined?("#{klass}::KLASS")
|
|
77
|
+
klass::KLASS
|
|
78
|
+
else
|
|
79
|
+
klass
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
private_class_method :lookup
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Ecfr
|
|
2
|
+
module SearchService
|
|
3
|
+
class DateFacet < FacetBase
|
|
4
|
+
include FacetAttributeMethodDefinition
|
|
5
|
+
|
|
6
|
+
result_key :dates
|
|
7
|
+
|
|
8
|
+
attribute :count, as: :value
|
|
9
|
+
attribute :date, type: :date, as: :key
|
|
10
|
+
|
|
11
|
+
# @param [<Symbol, String>] type currently only supports :daily
|
|
12
|
+
# @return [<DateFacet>] counts by date
|
|
13
|
+
def self.search(type, options = {})
|
|
14
|
+
# no-op documentation only
|
|
15
|
+
super(type, options)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Ecfr
|
|
2
|
+
module SearchService
|
|
3
|
+
class FacetBase < Base
|
|
4
|
+
COUNTS_PATH = "v1/counts"
|
|
5
|
+
|
|
6
|
+
#
|
|
7
|
+
# Retrive counts of changed CFR sections by date
|
|
8
|
+
#
|
|
9
|
+
# @param [<Hash>] args valid facet search parameters
|
|
10
|
+
# @option options [<Ecfr::SearchService::ContentVersion::Hierarchy>] :hierarchy levels of CFR hierarchy to limit the search to
|
|
11
|
+
# @option options [<String>] :last_modified_after ISO date
|
|
12
|
+
# @option options [<String>] :last_modified_on_or_after ISO date
|
|
13
|
+
# @option options [<String>] :last_modified_before ISO date
|
|
14
|
+
# @option options [<String>] :last_modified_on_or_before ISO date
|
|
15
|
+
# @option options [<String>] :query search terms
|
|
16
|
+
# @option options [<Boolean>] :reserved whether counts should be for Reserved content (default false)
|
|
17
|
+
# @option options [<Boolean>] :substantive whether counts should be for substantive content (default true)
|
|
18
|
+
#
|
|
19
|
+
# @return [<DateFacet>] counts by date
|
|
20
|
+
#
|
|
21
|
+
def self.search(type, args = {})
|
|
22
|
+
prepare_search_options(args)
|
|
23
|
+
|
|
24
|
+
perform(
|
|
25
|
+
:get,
|
|
26
|
+
counts_path(type),
|
|
27
|
+
params: args
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.counts_path(type)
|
|
32
|
+
"#{COUNTS_PATH}/#{type}"
|
|
33
|
+
end
|
|
34
|
+
private_class_method :counts_path
|
|
35
|
+
|
|
36
|
+
VALID_SEARCH_OPTIONS = %i[
|
|
37
|
+
hierarchy last_modified_after last_modified_on_or_after
|
|
38
|
+
last_modified_before last_modified_on_or_before query reserved
|
|
39
|
+
substantive
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
def self.prepare_search_options(args)
|
|
43
|
+
args.deep_symbolize_keys!
|
|
44
|
+
args.slice!(*VALID_SEARCH_OPTIONS)
|
|
45
|
+
|
|
46
|
+
if args[:hierarchy]
|
|
47
|
+
args[:hierarchy] = args[:hierarchy].slice(
|
|
48
|
+
*Ecfr::Constants::Hierarchy::HIERARCHY_LEVELS.map(&:to_sym)
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
private_class_method :prepare_search_options
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module Ecfr
|
|
2
|
+
module SearchService
|
|
3
|
+
class TitleFacet < FacetBase
|
|
4
|
+
include FacetAttributeMethodDefinition
|
|
5
|
+
|
|
6
|
+
result_key :titles
|
|
7
|
+
|
|
8
|
+
attribute :count, as: :value
|
|
9
|
+
attribute :title, as: :key
|
|
10
|
+
|
|
11
|
+
# @return [<TitleFacet>] counts by title
|
|
12
|
+
def self.search(options = {})
|
|
13
|
+
type = "titles"
|
|
14
|
+
super(type, options)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
module Ecfr
|
|
2
|
+
module SubscriptionsService
|
|
3
|
+
class Base < Ecfr::Base
|
|
4
|
+
require_relative "status"
|
|
5
|
+
|
|
6
|
+
require_relative "subscription"
|
|
7
|
+
|
|
8
|
+
SERVICE_PATH = "/api/subscriptions"
|
|
9
|
+
|
|
10
|
+
def self.base_url
|
|
11
|
+
Ecfr.config.subscriptions_service_url || Ecfr.config.base_url
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.service_name
|
|
15
|
+
"Subscriptions Service"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
module Ecfr
|
|
2
|
+
module SubscriptionsService
|
|
3
|
+
class Subscription < Base
|
|
4
|
+
result_key :subscriptions
|
|
5
|
+
|
|
6
|
+
attribute :title,
|
|
7
|
+
desc: "a description of the subscription"
|
|
8
|
+
|
|
9
|
+
attribute :delivery_count,
|
|
10
|
+
type: :integer,
|
|
11
|
+
desc: "the number of times the subscription has been delivered"
|
|
12
|
+
attribute :id,
|
|
13
|
+
type: :integer,
|
|
14
|
+
desc: "the subscription id"
|
|
15
|
+
|
|
16
|
+
attribute :created_at,
|
|
17
|
+
type: :date,
|
|
18
|
+
desc: "date the subscription was created"
|
|
19
|
+
attribute :last_delivered_at,
|
|
20
|
+
type: :date,
|
|
21
|
+
desc: "last date this subscription had matches and was delivered"
|
|
22
|
+
|
|
23
|
+
# TODO: upgrade to a class
|
|
24
|
+
|
|
25
|
+
# @return [Hash] with "query", and "hierarchy" keys
|
|
26
|
+
attribute :parameters,
|
|
27
|
+
desc: "the subscription search parameters"
|
|
28
|
+
|
|
29
|
+
SUBSCRIPTIONS_PATH = "v1/subscriptions"
|
|
30
|
+
|
|
31
|
+
#
|
|
32
|
+
# Retrive a list of subscriptions for a user
|
|
33
|
+
#
|
|
34
|
+
# @param [<Integer>] user_id id of user
|
|
35
|
+
#
|
|
36
|
+
# @return [[<Subscription>]] an array of subscriptions
|
|
37
|
+
#
|
|
38
|
+
def self.get_subscriptions(user_id)
|
|
39
|
+
perform(
|
|
40
|
+
:get,
|
|
41
|
+
"#{SUBSCRIPTIONS_PATH}/#{user_id}.json",
|
|
42
|
+
client_options: basic_auth_client_options
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
#
|
|
47
|
+
# Create a subscription for a user
|
|
48
|
+
#
|
|
49
|
+
# @param [<Integer>] user_id id of user
|
|
50
|
+
# @param [<Hash>] subscription_data arguments
|
|
51
|
+
# required to create a subscription
|
|
52
|
+
# @option subscription_data [String] requesting_ip (required)
|
|
53
|
+
# @option subscription_data [Hash] search (required)
|
|
54
|
+
# @option subscription_data [String] search[:query] subscription search terms
|
|
55
|
+
# @option subscription_data [Ecfr::Common::Hierarchy] search[:hierarchy] hierarchy to limit subscription search
|
|
56
|
+
#
|
|
57
|
+
# @return [<Subscription>] the created subscription
|
|
58
|
+
#
|
|
59
|
+
def self.create_subscription(user_id, subscription_data)
|
|
60
|
+
perform(
|
|
61
|
+
:post,
|
|
62
|
+
"#{SUBSCRIPTIONS_PATH}/#{user_id}",
|
|
63
|
+
params: subscription_data,
|
|
64
|
+
client_options: basic_auth_client_options,
|
|
65
|
+
perform_options: {attributes_key: "subscription"}
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
#
|
|
70
|
+
# Delete a subscription
|
|
71
|
+
#
|
|
72
|
+
# @param [<Integer>] user_id id of user
|
|
73
|
+
# @param [<String>] token unique delete token
|
|
74
|
+
# @param [<String>] subscription_id id of subscription
|
|
75
|
+
#
|
|
76
|
+
# @return [[<Subscription>, <Integer>]] the deleted subscription and response code
|
|
77
|
+
#
|
|
78
|
+
def self.delete_subscription(user_id, token, subscription_id)
|
|
79
|
+
unsubscribe_data = {
|
|
80
|
+
token: token,
|
|
81
|
+
user_id: user_id,
|
|
82
|
+
subscription_id: subscription_id
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
subscription = perform(
|
|
86
|
+
:delete,
|
|
87
|
+
"#{SUBSCRIPTIONS_PATH}/unsubscribe",
|
|
88
|
+
params: unsubscribe_data,
|
|
89
|
+
client_options: basic_auth_client_options,
|
|
90
|
+
perform_options: {attributes_key: "subscription"}
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
[subscription, subscription.response_status]
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class Ecfr::AdminService::EcfrCorrection
|
|
2
|
+
extend ResponseHelper
|
|
3
|
+
|
|
4
|
+
def self.response_for(corrections)
|
|
5
|
+
results = {
|
|
6
|
+
ecfr_corrections: corrections.is_a?(Array) ? corrections : [corrections]
|
|
7
|
+
}.to_json
|
|
8
|
+
|
|
9
|
+
build(
|
|
10
|
+
response: stubbed_response(results)
|
|
11
|
+
)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class Ecfr::SearchService::ContentVersion::Result
|
|
2
|
+
extend ResponseHelper
|
|
3
|
+
|
|
4
|
+
def self.response_for(content_versions)
|
|
5
|
+
content_versions = content_versions.is_a?(Array) ? content_versions : [content_versions]
|
|
6
|
+
|
|
7
|
+
results = {
|
|
8
|
+
results: content_versions,
|
|
9
|
+
meta: content_versions.first.fetch("meta", nil)
|
|
10
|
+
}.compact
|
|
11
|
+
|
|
12
|
+
build(
|
|
13
|
+
response: stubbed_response(results.to_json)
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class Ecfr::VersionerService::Ancestors
|
|
2
|
+
extend ResponseHelper
|
|
3
|
+
|
|
4
|
+
def self.response_for(ancestors)
|
|
5
|
+
# ancestors can be a hash of attributes from the :ancestors factory,
|
|
6
|
+
# or one+ NodeSummary attribute hashes from the :node_summary
|
|
7
|
+
# factory
|
|
8
|
+
results = if ancestors.is_a?(Hash) && ancestors.key?("ancestors")
|
|
9
|
+
ancestors
|
|
10
|
+
else
|
|
11
|
+
{
|
|
12
|
+
ancestors: ancestors.is_a?(Array) ? ancestors : [ancestors]
|
|
13
|
+
}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
build(
|
|
17
|
+
response: stubbed_response(results.to_json)
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class Ecfr::VersionerService::Title
|
|
2
|
+
extend ResponseHelper
|
|
3
|
+
|
|
4
|
+
def self.response_for(titles)
|
|
5
|
+
titles = titles.is_a?(Array) ? titles : [titles]
|
|
6
|
+
|
|
7
|
+
results = {
|
|
8
|
+
titles: titles,
|
|
9
|
+
meta: titles.first.fetch("meta", nil)
|
|
10
|
+
}.compact
|
|
11
|
+
|
|
12
|
+
build(
|
|
13
|
+
response: stubbed_response(results.to_json)
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
FactoryBot.define do
|
|
2
|
+
factory :cfr_reference, class: "Ecfr::AdminService::EcfrCorrection::CfrReference" do
|
|
3
|
+
skip_create
|
|
4
|
+
|
|
5
|
+
cfr_reference { "1 CFR 1" }
|
|
6
|
+
hierarchy {
|
|
7
|
+
ecfr_attribute_hash(:hierarchy, title: "1", part: "1")
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
initialize_with {
|
|
11
|
+
new(attributes.deep_stringify_keys)
|
|
12
|
+
}
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
FactoryBot.define do
|
|
2
|
+
factory :ecfr_correction, class: "Ecfr::AdminService::EcfrCorrection" do
|
|
3
|
+
skip_create
|
|
4
|
+
|
|
5
|
+
corrective_action { "corrected" }
|
|
6
|
+
fr_citation { "84 FR 12345" }
|
|
7
|
+
|
|
8
|
+
id { 1 }
|
|
9
|
+
position { 1 }
|
|
10
|
+
title { 1 }
|
|
11
|
+
year { correction_year }
|
|
12
|
+
|
|
13
|
+
error_corrected { Date.parse("#{year}-03-03") }
|
|
14
|
+
error_occurred { Date.parse("#{year}-01-01") }
|
|
15
|
+
last_modified { error_corrected }
|
|
16
|
+
|
|
17
|
+
cfr_references {
|
|
18
|
+
[ecfr_attribute_hash(:cfr_reference)]
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
display_in_toc { false }
|
|
22
|
+
|
|
23
|
+
initialize_with {
|
|
24
|
+
new(attributes.deep_stringify_keys)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
transient do
|
|
28
|
+
correction_year { 2017 }
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
FactoryBot.define do
|
|
2
|
+
factory :issue, class: "Ecfr::AdminService::Issue" do
|
|
3
|
+
skip_create
|
|
4
|
+
|
|
5
|
+
description { "January 1, 2019" }
|
|
6
|
+
|
|
7
|
+
titles { [5, 7, 9] }
|
|
8
|
+
|
|
9
|
+
end_date { "2019-01-01" }
|
|
10
|
+
issue_date { "2019-01-01" }
|
|
11
|
+
start_date { "2019-01-01" }
|
|
12
|
+
|
|
13
|
+
changes {
|
|
14
|
+
[ecfr_attribute_hash(:issue_change)]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
initialize_with {
|
|
18
|
+
new(attributes.deep_stringify_keys)
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
FactoryBot.define do
|
|
2
|
+
factory :hierarchy, class: "Ecfr::Common::Hierarchy" do
|
|
3
|
+
skip_create
|
|
4
|
+
|
|
5
|
+
title { nil }
|
|
6
|
+
subtitle { nil }
|
|
7
|
+
chapter { nil }
|
|
8
|
+
subchapter { nil }
|
|
9
|
+
part { nil }
|
|
10
|
+
subpart { nil }
|
|
11
|
+
subject_group { nil }
|
|
12
|
+
section { nil }
|
|
13
|
+
appendix { nil }
|
|
14
|
+
|
|
15
|
+
initialize_with {
|
|
16
|
+
new(attributes.deep_stringify_keys)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
trait :with_defaults do
|
|
20
|
+
title { "1" }
|
|
21
|
+
subtitle { "A" }
|
|
22
|
+
chapter { "I" }
|
|
23
|
+
subchapter { "I" }
|
|
24
|
+
part { "1" }
|
|
25
|
+
subpart { "B" }
|
|
26
|
+
subject_group { nil }
|
|
27
|
+
section { "1.1" }
|
|
28
|
+
appendix { nil }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
trait :appendix do
|
|
32
|
+
section { nil }
|
|
33
|
+
appendix { "Appendix A to Part 1" }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
FactoryBot.define do
|
|
2
|
+
factory :origin, class: "Ecfr::RendererService::Origin" do
|
|
3
|
+
skip_create
|
|
4
|
+
|
|
5
|
+
identifier { "121" }
|
|
6
|
+
label_level { "Part 121" }
|
|
7
|
+
level { "part" }
|
|
8
|
+
link { "/current/title-40/part-121" }
|
|
9
|
+
title { "Part 121" }
|
|
10
|
+
|
|
11
|
+
authority {
|
|
12
|
+
["Sec. 21 (b) and (c), 84 Stat. 91 (<a href=\"https://www.govinfo.gov/link/uscode/33/1171\" class=\"usc external\" target=\"_blank\" rel=\"noopener noreferrer\">33 U.S.C. 1171(b)</a> (1970)); Reorganization Plan No. 3 of 1970. "]
|
|
13
|
+
}
|
|
14
|
+
source {
|
|
15
|
+
["<a href=\"https://www.federalregister.gov/citation/36-FR-22487\" class=\"fr-reference\" data-reference=\"36 FR 22487\">36 FR 22487</a>, Nov. 25, 1971, unless otherwise noted. Redesignated at <a href=\"https://www.federalregister.gov/citation/37-FR-21441\" class=\"fr-reference\" data-reference=\"37 FR 21441\">37 FR 21441</a>, Oct. 11, 1972, and further redesignated at <a href=\"https://www.federalregister.gov/citation/44-FR-32899\" class=\"fr-reference\" data-reference=\"44 FR 32899\">44 FR 32899</a>, June 7, 1979. "]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
current { false }
|
|
19
|
+
|
|
20
|
+
hierarchy {
|
|
21
|
+
ecfr_attribute_hash(:hierarchy,
|
|
22
|
+
title: "40",
|
|
23
|
+
chapter: "I",
|
|
24
|
+
subchapter: "D",
|
|
25
|
+
part: "121")
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
initialize_with {
|
|
29
|
+
new(attributes.deep_stringify_keys)
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
FactoryBot.define do
|
|
2
|
+
factory :content_version_count, class: "Ecfr::SearchService::ContentVersion::Count" do
|
|
3
|
+
skip_create
|
|
4
|
+
|
|
5
|
+
meta {
|
|
6
|
+
{
|
|
7
|
+
description: "Description of results...",
|
|
8
|
+
total_count: total_count
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
transient do
|
|
13
|
+
total_count { 10 }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
initialize_with {
|
|
17
|
+
new(attributes.deep_stringify_keys)
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
FactoryBot.define do
|
|
2
|
+
factory :content_version_result, class: "Ecfr::SearchService::ContentVersion::Result" do
|
|
3
|
+
skip_create
|
|
4
|
+
|
|
5
|
+
change_types { [] }
|
|
6
|
+
|
|
7
|
+
full_text_excerpt {
|
|
8
|
+
"Section 100.100 full text excerpt with <strong>formatting</strong>"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
hierarchy {
|
|
12
|
+
{
|
|
13
|
+
title: "10",
|
|
14
|
+
subtitle: "B",
|
|
15
|
+
chapter: "II",
|
|
16
|
+
subchapter: "H",
|
|
17
|
+
part: "100",
|
|
18
|
+
subpart: "D",
|
|
19
|
+
subject_group: nil,
|
|
20
|
+
section: (type == "Section") ? "100.100" : nil,
|
|
21
|
+
appendix: (type == "Appendix") ? "Appendix A to Subpart D of Part 100" : nil
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# defaults for these are generated in helpers based on the hierarchy
|
|
26
|
+
# provided - any provided here will override just those keys
|
|
27
|
+
headings { {} }
|
|
28
|
+
hierarchy_headings { {} }
|
|
29
|
+
|
|
30
|
+
reserved { false }
|
|
31
|
+
removed { false }
|
|
32
|
+
|
|
33
|
+
score { 16.946056 }
|
|
34
|
+
structure_index { 1 }
|
|
35
|
+
|
|
36
|
+
starts_on { "2017-01-03" }
|
|
37
|
+
ends_on { nil }
|
|
38
|
+
|
|
39
|
+
type { "Section" }
|
|
40
|
+
|
|
41
|
+
trait :appendix do
|
|
42
|
+
type { "Appendix" }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
meta {
|
|
46
|
+
{
|
|
47
|
+
current_page: current_page,
|
|
48
|
+
description: description,
|
|
49
|
+
min_date: min_date,
|
|
50
|
+
max_date: max_date,
|
|
51
|
+
max_score: max_score,
|
|
52
|
+
total_count: total_count,
|
|
53
|
+
total_pages: total_pages
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
transient do
|
|
58
|
+
current_page { 1 }
|
|
59
|
+
description { "Results for search terms x, y, and z" }
|
|
60
|
+
min_date { "2017-01-03" }
|
|
61
|
+
max_date { "2017-01-10" }
|
|
62
|
+
max_score { 1 }
|
|
63
|
+
total_count { 1 }
|
|
64
|
+
total_pages { 1 }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
initialize_with {
|
|
68
|
+
attrs = FactoryBotHelpers::EcfrGemInitializeHelpers.pre_initialize_attrs_for(
|
|
69
|
+
:content_version_result,
|
|
70
|
+
attributes
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
new(attrs.deep_stringify_keys)
|
|
74
|
+
}
|
|
75
|
+
end
|
|
76
|
+
end
|