Module: Inferno::DSL::FHIRClient
- Defined in:
- lib/inferno/dsl/fhir_client.rb
Overview
This module contains the FHIR DSL available to test writers.
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
Instance Method Summary collapse
-
#body_to_path(body) ⇒ Object
Converts a list of FHIR Parameters into a query string for GET requests.
-
#fetch_all_bundled_resources(resource_type:, bundle: resource, reply_handler: nil, client: :default, max_pages: 20, additional_resource_types: [], tags: []) ⇒ Array<FHIR::Resource>
Fetch all resources from a paginated FHIR bundle.
- #fetch_next_bundle(bundle, client, tags) ⇒ Object
- #fhir_class_from_resource_type(resource_type) ⇒ Object
-
#fhir_client(client = :default) ⇒ FHIR::Client
Return a previously defined FHIR client.
- #fhir_clients ⇒ Object
-
#fhir_create(resource, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR create interaction.
-
#fhir_delete(resource_type, id, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR delete interaction.
-
#fhir_get_capability_statement(client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Fetch the capability statement.
-
#fhir_history(resource_type = nil, id = nil, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR history interaction.
-
#fhir_operation(path, body: nil, client: :default, name: nil, headers: {}, operation_method: :post, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR operation.
-
#fhir_patch(resource_type, id, patchset, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR patch interaction.
-
#fhir_read(resource_type, id, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR read interaction.
-
#fhir_search(resource_type = nil, client: :default, params: {}, name: nil, search_method: :get, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR search interaction.
-
#fhir_transaction(bundle = nil, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR batch/transaction interaction.
-
#fhir_update(resource, id, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR update interaction.
-
#fhir_vread(resource_type, id, version_id, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR vread interaction.
- #find_fhir_client_definition(client) ⇒ Object
- #next_bundle_link(bundle) ⇒ Object
- #perform_refresh(client) ⇒ Object
-
#primitive_parameter?(param) ⇒ Boolean
Wrapper for checking if parameter contents are primitive.
-
#store_request_and_refresh_token(client, name, tags, &block) ⇒ Object
This method wraps a request to automatically refresh its access token if expired.
Class Method Details
.included(klass) ⇒ Object
41 42 43 44 45 46 |
# File 'lib/inferno/dsl/fhir_client.rb', line 41 def self.included(klass) klass.extend ClassMethods klass.extend Forwardable klass.include RequestStorage klass.include TCPExceptionHandler end |
Instance Method Details
#body_to_path(body) ⇒ Object
Converts a list of FHIR Parameters into a query string for GET requests
80 81 82 83 84 85 86 87 88 89 90 |
# File 'lib/inferno/dsl/fhir_client.rb', line 80 def body_to_path(body) query_hashes = body.parameter.map do |param| if primitive_parameter?(param) { param.name => param.to_hash.except('name').values[0] } else Inferno::Application[:logger].error "Cannot use GET request with non-primitive datatype #{param.name}" raise ArgumentError, "Cannot use GET request with non-primitive datatype #{param.name}" end end query_hashes.map(&:to_query).join('&') end |
#fetch_all_bundled_resources(resource_type:, bundle: resource, reply_handler: nil, client: :default, max_pages: 20, additional_resource_types: [], tags: []) ⇒ Array<FHIR::Resource>
Fetch all resources from a paginated FHIR bundle
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/inferno/dsl/fhir_client.rb', line 345 def fetch_all_bundled_resources( # rubocop:disable Metrics/CyclomaticComplexity resource_type:, bundle: resource, reply_handler: nil, client: :default, max_pages: 20, additional_resource_types: [], tags: [] ) page_count = 1 resources = [] while bundle && page_count <= max_pages resources += bundle.entry&.map { |entry| entry&.resource } || [] reply_handler&.call(response) break if next_bundle_link(bundle).blank? bundle = fetch_next_bundle(bundle, client, ) page_count += 1 end valid_resource_types = [resource_type, 'OperationOutcome'].concat(additional_resource_types) invalid_resource_types = resources.reject { |entry| valid_resource_types.include? entry.resourceType } .map(&:resourceType) .uniq if invalid_resource_types.any? info "Received resource type(s) #{invalid_resource_types.join(', ')} in search bundle, " \ "but only expected resource types #{valid_resource_types.join(', ')}. " \ 'This is unusual but allowed if the server believes additional resource types are relevant.' end resources rescue JSON::ParserError Inferno::Application[:logger].error "Could not resolve next bundle: #{next_bundle_link(bundle)}" resources end |
#fetch_next_bundle(bundle, client, tags) ⇒ Object
431 432 433 434 435 436 437 |
# File 'lib/inferno/dsl/fhir_client.rb', line 431 def fetch_next_bundle(bundle, client, ) reply = fhir_client(client).raw_read_url(next_bundle_link(bundle)) store_request('outgoing', tags:) { reply } return unless request.status == 200 fhir_client(client).parse_reply(FHIR::Bundle, fhir_client(client).default_format, reply) end |
#fhir_class_from_resource_type(resource_type) ⇒ Object
Make this a FHIR class method? Something like FHIR.class_for(resource_type)
389 390 391 |
# File 'lib/inferno/dsl/fhir_client.rb', line 389 def fhir_class_from_resource_type(resource_type) FHIR.const_get(resource_type.to_s.camelize) end |
#fhir_client(client = :default) ⇒ FHIR::Client
Return a previously defined FHIR client
53 54 55 56 |
# File 'lib/inferno/dsl/fhir_client.rb', line 53 def fhir_client(client = :default) fhir_clients[client] ||= FHIRClientBuilder.new.build(self, find_fhir_client_definition(client)) end |
#fhir_clients ⇒ Object
63 64 65 |
# File 'lib/inferno/dsl/fhir_client.rb', line 63 def fhir_clients @fhir_clients ||= {} end |
#fhir_create(resource, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR create interaction.
162 163 164 165 166 167 168 |
# File 'lib/inferno/dsl/fhir_client.rb', line 162 def fhir_create(resource, client: :default, name: nil, tags: []) store_request_and_refresh_token(fhir_client(client), name, ) do tcp_exception_handler do fhir_client(client).create(resource) end end end |
#fhir_delete(resource_type, id, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR delete interaction.
309 310 311 312 313 314 315 |
# File 'lib/inferno/dsl/fhir_client.rb', line 309 def fhir_delete(resource_type, id, client: :default, name: nil, tags: []) store_request('outgoing', name:, tags:) do tcp_exception_handler do fhir_client(client).destroy(fhir_class_from_resource_type(resource_type), id) end end end |
#fhir_get_capability_statement(client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Fetch the capability statement.
145 146 147 148 149 150 151 152 |
# File 'lib/inferno/dsl/fhir_client.rb', line 145 def fhir_get_capability_statement(client: :default, name: nil, tags: []) store_request_and_refresh_token(fhir_client(client), name, ) do tcp_exception_handler do fhir_client(client).conformance_statement fhir_client(client).reply end end end |
#fhir_history(resource_type = nil, id = nil, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR history interaction.
249 250 251 252 253 254 255 256 257 258 259 260 261 |
# File 'lib/inferno/dsl/fhir_client.rb', line 249 def fhir_history(resource_type = nil, id = nil, client: :default, name: nil, tags: []) store_request_and_refresh_token(fhir_client(client), name, ) do tcp_exception_handler do if id fhir_client(client).resource_instance_history(fhir_class_from_resource_type(resource_type), id) elsif resource_type fhir_client(client).resource_history(fhir_class_from_resource_type(resource_type)) else fhir_client(client).all_history end end end end |
#fhir_operation(path, body: nil, client: :default, name: nil, headers: {}, operation_method: :post, tags: []) ⇒ Inferno::Entities::Request
This is a placeholder method until the FHIR::Client supports general operations. Note that while both POST and GET methods are allowed, GET is only allowed when the operation does not affect the server’s state. See build.fhir.org/operationdefinition-definitions.html#OperationDefinition.affectsState
Currently does not allow for repeated parameters if using GET
Perform a FHIR operation
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/inferno/dsl/fhir_client.rb', line 110 def fhir_operation( path, body: nil, client: :default, name: nil, headers: {}, operation_method: :post, tags: [] ) store_request_and_refresh_token(fhir_client(client), name, ) do tcp_exception_handler do operation_headers = fhir_client(client).fhir_headers operation_headers.merge!('Content-Type' => 'application/fhir+json') if body.present? operation_headers.merge!(headers) if headers.present? case operation_method when :post fhir_client(client).send(:post, path, body, operation_headers) when :get path = "#{path}?#{body_to_path(body)}" if body.present? fhir_client(client).send(:get, path, operation_headers) else Inferno::Application[:logger].error "Cannot perform #{operation_method} requests, use GET or POST" raise ArgumentError, "Cannot perform #{operation_method} requests, use GET or POST" end end end end |
#fhir_patch(resource_type, id, patchset, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR patch interaction.
232 233 234 235 236 237 238 |
# File 'lib/inferno/dsl/fhir_client.rb', line 232 def fhir_patch(resource_type, id, patchset, client: :default, name: nil, tags: []) store_request_and_refresh_token(fhir_client(client), name, ) do tcp_exception_handler do fhir_client(client).partial_update(fhir_class_from_resource_type(resource_type), id, patchset) end end end |
#fhir_read(resource_type, id, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR read interaction.
179 180 181 182 183 184 185 |
# File 'lib/inferno/dsl/fhir_client.rb', line 179 def fhir_read(resource_type, id, client: :default, name: nil, tags: []) store_request_and_refresh_token(fhir_client(client), name, ) do tcp_exception_handler do fhir_client(client).read(fhir_class_from_resource_type(resource_type), id) end end end |
#fhir_search(resource_type = nil, client: :default, params: {}, name: nil, search_method: :get, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR search interaction.
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 |
# File 'lib/inferno/dsl/fhir_client.rb', line 273 def fhir_search( resource_type = nil, client: :default, params: {}, name: nil, search_method: :get, tags: [] ) search = if search_method == :post { body: params } else { parameters: params } end store_request_and_refresh_token(fhir_client(client), name, ) do tcp_exception_handler do if resource_type fhir_client(client) .search(fhir_class_from_resource_type(resource_type), { search: }) else fhir_client(client).search_all({ search: }) end end end end |
#fhir_transaction(bundle = nil, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR batch/transaction interaction.
325 326 327 328 329 330 331 332 |
# File 'lib/inferno/dsl/fhir_client.rb', line 325 def fhir_transaction(bundle = nil, client: :default, name: nil, tags: []) store_request('outgoing', name:, tags:) do tcp_exception_handler do fhir_client(client).transaction_bundle = bundle if bundle.present? fhir_client(client).end_transaction end end end |
#fhir_update(resource, id, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR update interaction.
214 215 216 217 218 219 220 |
# File 'lib/inferno/dsl/fhir_client.rb', line 214 def fhir_update(resource, id, client: :default, name: nil, tags: []) store_request_and_refresh_token(fhir_client(client), name, ) do tcp_exception_handler do fhir_client(client).update(resource, id) end end end |
#fhir_vread(resource_type, id, version_id, client: :default, name: nil, tags: []) ⇒ Inferno::Entities::Request
Perform a FHIR vread interaction.
197 198 199 200 201 202 203 |
# File 'lib/inferno/dsl/fhir_client.rb', line 197 def fhir_vread(resource_type, id, version_id, client: :default, name: nil, tags: []) store_request_and_refresh_token(fhir_client(client), name, ) do tcp_exception_handler do fhir_client(client).vread(fhir_class_from_resource_type(resource_type), id, version_id) end end end |
#find_fhir_client_definition(client) ⇒ Object
58 59 60 |
# File 'lib/inferno/dsl/fhir_client.rb', line 58 def find_fhir_client_definition(client) self.class.find_fhir_client_definition(client) end |
#next_bundle_link(bundle) ⇒ Object
440 441 442 |
# File 'lib/inferno/dsl/fhir_client.rb', line 440 def next_bundle_link(bundle) bundle&.link&.find { |link| link.relation == 'next' }&.url end |
#perform_refresh(client) ⇒ Object
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 |
# File 'lib/inferno/dsl/fhir_client.rb', line 405 def perform_refresh(client) credentials = client.auth_info || client.oauth_credentials post( credentials.token_url, body: credentials.oauth2_refresh_params, headers: credentials.oauth2_refresh_headers ) return if request.status != 200 credentials.update_from_response_body(request) if credentials.name.present? Inferno::Repositories::SessionData.new.save( name: credentials.name, value: credentials, type: credentials.is_a?(Inferno::DSL::AuthInfo) ? 'auth_info' : 'oauth_credentials', test_session_id: ) end rescue StandardError => e Inferno::Application[:logger].error "Unable to refresh token: #{e.}" end |
#primitive_parameter?(param) ⇒ Boolean
Wrapper for checking if parameter contents are primitive
71 72 73 74 |
# File 'lib/inferno/dsl/fhir_client.rb', line 71 def primitive_parameter?(param) param_val = param.to_hash.except('name') param_val.any? { |datatype, param_value| FHIR.primitive?(datatype: datatype[5..], value: param_value) } end |
#store_request_and_refresh_token(client, name, tags, &block) ⇒ Object
This method wraps a request to automatically refresh its access token if expired. It’s combined with ‘store_request` so that all of the fhir request methods don’t have to be wrapped twice.
397 398 399 400 401 402 |
# File 'lib/inferno/dsl/fhir_client.rb', line 397 def store_request_and_refresh_token(client, name, , &block) store_request('outgoing', name:, tags:) do perform_refresh(client) if client.need_to_refresh? && client.able_to_refresh? block.call end end |