Class: Ecfr::VersionerService::Ancestors
- Extended by:
- ResponseHelper
- Defined in:
- lib/ecfr/versioner_service/ancestors.rb,
lib/ecfr/versioner_service/ancestors/node_summary.rb,
lib/ecfr/versioner_service/ancestors/metadata_node_info.rb,
lib/ecfr/testing/extensions/versioner_service/ancestors_extensions.rb
Overview
Ancestors is used to retrieve data about the hierarchical structure of the CFR. The ‘.find` method expects to be provided a limited hierarchy, for example just a title and part - and will return the ancestors in the hierarchy that part is located within.
As a performance optimization the full structure hierarchy to the provided hierarchy can also be returned as part of the response.
Previous and next node attributes are used for navigating around the same level of hierarchy, for example from subpart to subpart, or from section to section even when the next section is in a sibling part (last section of one subpart -> first section of the next).
Source xml filesize is an estimate of the size of the content that would be returned if the provided hierarchy was retrieved.
Defined Under Namespace
Classes: MetadataNodeInfo, NodeSummary
Constant Summary collapse
- ANCESTORS_PATH =
"v1/ancestry"
- PARAMETERS_NOT_AFFECTING_BASE_RESPONSE =
these parameters add items to the base response but do not affect our ability to cache that base response
%i[metadata]
- SIDELOAD_PARAMETERS =
%i[structure descendant_depth]
Constants inherited from Base
Base::SUPPORTED_ARRAY_ACCESSORS
Instance Attribute Summary collapse
-
#ancestors ⇒ [NodeSummary]
(also: #all)
readonly
an array of ancestor hierarchy levels of the hierarchy found.
-
#next_node ⇒ MetadataNodeInfo
readonly
the next node in the hierarchy.
-
#previous_node ⇒ MetadataNodeInfo
readonly
the previous node in the hierarchy.
-
#source_xml_filesize ⇒ Integer
readonly
the approximate file size of the xml for the hierarchy found.
-
#structure ⇒ Ecfr::VersionerService::Structure
readonly
the full hierarchy to the requested (limited) hierarchy.
Attributes inherited from Base
#metadata, #request_data, #response_status, #results
Class Method Summary collapse
-
.cache_base_response(response, method, path, params) ⇒ Object
if the request only includes optional parameters that don’t affect the basic part of the response, then we can cache a base form of that response by removing those optional return items (this keeps the cache consistent across request by not including extra items).
-
.find(date:, title_number:, hierarchy_args: {}, options: {}) ⇒ <Ancestors>
Retrive ancestor date about a given (limited) hierarchy on a particular date.
-
.only_safe_params?(params) ⇒ Boolean
private_class_method :cache_base_response.
- .response_for(ancestors) ⇒ Object
Instance Method Summary collapse
- #each ⇒ Object
-
#initialize(attributes, options = {}) ⇒ Ancestors
constructor
We overload the inherited initialize method in order to modify how we represent the response to the end user.
Methods included from ResponseHelper
Methods inherited from Base
base_url, service_name, service_path
Methods inherited from Base
basic_auth_client_options, metadata, metadata_key, result_key
Methods included from Extensible
Methods included from AttributeMethodDefinition
Methods inherited from Client
build, cache_key, client, client_pool, delete, execute, get, handle_response, perform, post, purge
Methods included from ParallelClient
Constructor Details
#initialize(attributes, options = {}) ⇒ Ancestors
We overload the inherited initialize method in order to modify how we represent the response to the end user.
- we add a `hierarchy` key to each ancestor that includes it's parents
- we set a `structure` attribute if structure was returned in the
response
159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/ecfr/versioner_service/ancestors.rb', line 159 def initialize(attributes, = {}) super(attributes, ) ancestors.each_with_object({}) do |ancestor, hsh| hsh[ancestor.type] = ancestor.identifier ancestor.attributes["hierarchy"] = hsh.dup end # force casting of structure to a structure object # such that it gets cached immediately - see # Structure sideloaded format for details structure if attributes["structure"] end |
Instance Attribute Details
#ancestors ⇒ [NodeSummary] (readonly) Also known as: all
an array of ancestor hierarchy levels of the hierarchy found
28 29 30 |
# File 'lib/ecfr/versioner_service/ancestors.rb', line 28 attribute :ancestors, type: Array(NodeSummary), desc: "an array of ancestor hierarchy levels of the hierarchy found" |
#next_node ⇒ MetadataNodeInfo (readonly)
the next node in the hierarchy
42 43 44 |
# File 'lib/ecfr/versioner_service/ancestors.rb', line 42 :next_node, type: MetadataNodeInfo, desc: "the next node in the hierarchy" |
#previous_node ⇒ MetadataNodeInfo (readonly)
the previous node in the hierarchy
39 40 41 |
# File 'lib/ecfr/versioner_service/ancestors.rb', line 39 :previous_node, type: MetadataNodeInfo, desc: "the previous node in the hierarchy" |
#source_xml_filesize ⇒ Integer (readonly)
the approximate file size of the xml for the hierarchy found
46 47 48 |
# File 'lib/ecfr/versioner_service/ancestors.rb', line 46 :source_xml_filesize, type: :integer, desc: "the approximate file size of the xml for the hierarchy found" |
#structure ⇒ Ecfr::VersionerService::Structure (readonly)
the full hierarchy to the requested (limited) hierarchy
33 34 35 36 37 |
# File 'lib/ecfr/versioner_service/ancestors.rb', line 33 attribute :structure, type: Ecfr::VersionerService::Structure, value_key: "structure", options: {format: "sideloaded", self: true}, desc: "the full hierarchy to the requested (limited) hierarchy" |
Class Method Details
.cache_base_response(response, method, path, params) ⇒ Object
if the request only includes optional parameters that don’t affect the basic part of the response, then we can cache a base form of that response by removing those optional return items (this keeps the cache consistent across request by not including extra items).
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/ecfr/versioner_service/ancestors.rb', line 107 def self.cache_base_response(response, method, path, params) non_hierarchy_params = params.except( *Ecfr::Constants::Hierarchy::HIERARCHY_LEVELS.map(&:to_sym) ) if only_safe_params?(non_hierarchy_params) cache_key = cache_key(method, path, params.except(*SIDELOAD_PARAMETERS)) # in the case the the response is the base response the cache keys # will match - fetch will just return that and this will essentially # be a no op RequestStore.fetch(cache_key) do excluded_items = params.key?(:metadata) ? [:structure] : [:metadata, :structure] response_body = JSON.parse(response.body) .except(*excluded_items.map(&:to_s)) # return a ducktyped object like the response object OpenStruct.new( body: response_body.to_json, status: response.status ) end end end |
.find(date:, title_number:, hierarchy_args: {}, options: {}) ⇒ <Ancestors>
Retrive ancestor date about a given (limited) hierarchy on a particular date
78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/ecfr/versioner_service/ancestors.rb', line 78 def self.find(date:, title_number:, hierarchy_args: {}, options: {}) # ActiveSupport::HashWithIndifferentAccess does not have a ! method hierarchy_args = hierarchy_args.symbolize_keys = .symbolize_keys = hierarchy_args.merge().except(:title, :metadata) [:metadata] = true perform( :get, ancestors_path(date, title_number), params: .compact ) end |
.only_safe_params?(params) ⇒ Boolean
private_class_method :cache_base_response
135 136 137 138 139 140 141 |
# File 'lib/ecfr/versioner_service/ancestors.rb', line 135 def self.only_safe_params?(params) # are all of the params keys included in the one of the lists? params.keys.all? do |p| (PARAMETERS_NOT_AFFECTING_BASE_RESPONSE + SIDELOAD_PARAMETERS).include?(p) end end |
.response_for(ancestors) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# File 'lib/ecfr/testing/extensions/versioner_service/ancestors_extensions.rb', line 4 def self.response_for(ancestors) # ancestors can be a hash of attributes from the :ancestors factory, # or one+ NodeSummary attribute hashes from the :node_summary # factory results = if ancestors.is_a?(Hash) && ancestors.key?("ancestors") ancestors else { ancestors: ancestors.is_a?(Array) ? ancestors : [ancestors] } end build( response: stubbed_response(results.to_json) ) end |
Instance Method Details
#each ⇒ Object
148 149 150 |
# File 'lib/ecfr/versioner_service/ancestors.rb', line 148 def each ancestors.each { |result| yield result } end |