fhir_client 1.0.2 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7e798b19840921ad0695ecacbb3dcd0d7f662da9
4
- data.tar.gz: c176b2138418157c1fc357c4c1fd18c335625692
3
+ metadata.gz: d0b559d338d7f9f46f075f1b81519fedaf482ffe
4
+ data.tar.gz: 5dae2a7c67ee80258a9c56c5c88179dab7dbe44e
5
5
  SHA512:
6
- metadata.gz: f05664d0b45e1657d7147069ef1d04c59af7b722e0a9f043729ca66e8af4a58df9d822f4ca4f01c13dfc99a97cfedb418057b94531eaf608858db1ed6de2991f
7
- data.tar.gz: 8417ee48735581a8bb2daef931af22bb0309e261dd163cabd6be225bfb4fbc61a6e10f33520d099581b2efe1fdfbfe6a5fc5bc908cc79772052d2623d7029eea
6
+ metadata.gz: eb511574de6b71e63af45ac89b6fb282ccdd1136b1934d24e68885afd3b9a29a4791beefde800c645dbb1de47de640ac50219f8d6773c7fba39905e46b02723a
7
+ data.tar.gz: b70ac6d8e90671845411f85af80db521174b33d5a8f5e8c1989a7d9c1eba50eb56f7849e8d65031b6095b3ef2abbb5623da1a9343c8579e7922726674ba248bd
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fhir_client (1.0.2)
4
+ fhir_client (1.6.0)
5
5
  activesupport (>= 3)
6
6
  addressable (>= 2.3)
7
- fhir_models (>= 0.3.1)
7
+ fhir_models (>= 1.6.0)
8
8
  oauth2 (~> 1.1)
9
9
  rest-client (~> 1.8)
10
10
  tilt (>= 1.1)
@@ -26,11 +26,11 @@ GEM
26
26
  coderay (1.1.1)
27
27
  date_time_precision (0.8.1)
28
28
  docile (1.1.5)
29
- domain_name (0.5.20160310)
29
+ domain_name (0.5.20160615)
30
30
  unf (>= 0.0.5, < 1.0.0)
31
31
  faraday (0.9.2)
32
32
  multipart-post (>= 1.2, < 3)
33
- fhir_models (0.3.1)
33
+ fhir_models (1.6.0)
34
34
  bcp47 (>= 0.3)
35
35
  date_time_precision (>= 0.8)
36
36
  mime-types (>= 1.16, < 3)
@@ -40,7 +40,7 @@ GEM
40
40
  domain_name (~> 0.5)
41
41
  i18n (0.7.0)
42
42
  json (1.8.2)
43
- jwt (1.5.1)
43
+ jwt (1.5.4)
44
44
  method_source (0.8.2)
45
45
  mime-types (2.99.2)
46
46
  mini_portile2 (2.1.0)
@@ -52,9 +52,9 @@ GEM
52
52
  nokogiri (1.6.8)
53
53
  mini_portile2 (~> 2.1.0)
54
54
  pkg-config (~> 1.1.7)
55
- oauth2 (1.1.0)
55
+ oauth2 (1.2.0)
56
56
  faraday (>= 0.8, < 0.10)
57
- jwt (~> 1.0, < 1.5.2)
57
+ jwt (~> 1.0)
58
58
  multi_json (~> 1.3)
59
59
  multi_xml (~> 0.5)
60
60
  rack (>= 1.2, < 3)
@@ -64,7 +64,7 @@ GEM
64
64
  method_source (~> 0.8.1)
65
65
  slop (~> 3.4)
66
66
  rack (1.6.4)
67
- rake (11.1.2)
67
+ rake (11.2.2)
68
68
  rest-client (1.8.0)
69
69
  http-cookie (>= 1.0.2, < 2.0)
70
70
  mime-types (>= 1.16, < 3.0)
data/README.md CHANGED
@@ -11,35 +11,50 @@ Supports:
11
11
  * Operations (e.g. `$everything`, `$validate`)
12
12
  * Support for OAuth2
13
13
 
14
- ### Getting Started
14
+ ## Getting Started
15
15
 
16
16
  $ bundle install
17
17
  $ bundle exec rake fhir:console
18
18
 
19
- ### Creating a Client
19
+ ## Creating a Client
20
20
  ```ruby
21
21
  client = FHIR::Client.new(url)
22
22
  ```
23
23
 
24
- ### Searching
24
+ This client supports two modes of operation: basic and advanced. The basic mode is useful for simple operations
25
+ because it promotes an ActiveRecord-like style of interaction. The advanced mode is less developer-friendly, but is currently necessary if you would like to use the entire range of operations exposed by FHIR.
26
+
27
+ ## Basic Usage
28
+
29
+ Associate the client with the model:
30
+
25
31
  ```ruby
26
- reply = client.search(FHIR::Patient, search: {parameters: {name: 'P'}})
27
- bundle = reply.resource
28
- patient = bundle.entry.first.resource
32
+ FHIR::Model.client = client
29
33
  ```
30
34
 
31
- ### Fetching a Bundle
35
+ The FHIR models can now be used to directly interact with a FHIR server.
36
+
32
37
  ```ruby
33
- reply = client.read_feed(FHIR::Patient) # fetch Bundle of Patients
34
- bundle = reply.resource
35
- bundle.entry.each do |entry|
36
- patient = entry.resource
37
- puts patient.name[0].text
38
- end
39
- puts reply.code # HTTP 200 (or whatever was returned)
40
- puts reply.body # Raw XML or JSON
38
+ # read an existing patient with an ID of 'example'
39
+ patient = FHIR::Patient.read('example')
40
+
41
+ # update a patient
42
+ patient.gender = 'female'
43
+ patient.update # saves the patient
44
+
45
+ # create a patient
46
+ patient = FHIR::Patient.create(name: {given: 'John', family: 'Doe'})
47
+
48
+ # search patients
49
+ results = FHIR::Patient.search(given: 'John', family: 'Doe')
50
+ results.count # results in an enumeration
51
+
52
+ # delete the recently created patient
53
+ patient.destroy
41
54
  ```
42
55
 
56
+ ## Advanced Usage
57
+
43
58
  ### CRUD Examples
44
59
  ```ruby
45
60
  # read an existing patient with id "example"
@@ -73,6 +88,25 @@ client.conditional_create(patient, ifNoneExist)
73
88
  client.destroy(FHIR::Patient, patient_id)
74
89
  ```
75
90
 
91
+ ### Searching
92
+ ```ruby
93
+ reply = client.search(FHIR::Patient, search: {parameters: {name: 'P'}})
94
+ bundle = reply.resource
95
+ patient = bundle.entry.first.resource
96
+ ```
97
+
98
+ ### Fetching a Bundle
99
+ ```ruby
100
+ reply = client.read_feed(FHIR::Patient) # fetch Bundle of Patients
101
+ bundle = reply.resource
102
+ bundle.entry.each do |entry|
103
+ patient = entry.resource
104
+ puts patient.name[0].text
105
+ end
106
+ puts reply.code # HTTP 200 (or whatever was returned)
107
+ puts reply.body # Raw XML or JSON
108
+ ```
109
+
76
110
  ### Transactions
77
111
  ```ruby
78
112
  # Create a patient
data/fhir_client.gemspec CHANGED
@@ -7,11 +7,11 @@ Gem::Specification.new do |s|
7
7
  s.email = "aquina@mitre.org"
8
8
  s.homepage = "https://github.com/hl7-fhir/fhir-svn"
9
9
  s.authors = ["Andre Quina", "Jason Walonoski", "Janoo Fernandes"]
10
- s.version = '1.0.2'
10
+ s.version = '1.6.0'
11
11
 
12
12
  s.files = s.files = `git ls-files`.split("\n")
13
13
 
14
- s.add_dependency 'fhir_models', '>= 0.3.1'
14
+ s.add_dependency 'fhir_models', '>= 1.6.0'
15
15
  s.add_dependency 'tilt', '>= 1.1'
16
16
  s.add_dependency 'rest-client', '~> 1.8'
17
17
  s.add_dependency 'oauth2', '~> 1.1'
@@ -0,0 +1,10 @@
1
+ class ClientException < Exception
2
+
3
+ attr_accessor :reply
4
+
5
+ def initialize(message, reply = nil)
6
+ super(message)
7
+ @reply = reply
8
+ end
9
+
10
+ end
@@ -196,25 +196,20 @@ module FHIR
196
196
 
197
197
  def fhir_headers(options={})
198
198
  FHIR::ResourceAddress.new.fhir_headers(options, @use_format_param)
199
- end
199
+ end
200
200
 
201
201
  def parse_reply(klass, format, response)
202
202
  $LOG.info "Parsing response with {klass: #{klass}, format: #{format}, code: #{response.code}}."
203
203
  return nil if ![200,201].include? response.code
204
204
  res = nil
205
205
  begin
206
- res = nil
207
- if(format.downcase.include?('xml'))
208
- res = FHIR::Xml.from_xml(response.body)
209
- else
210
- res = FHIR::Json.from_json(response.body)
211
- end
206
+ res = FHIR.from_contents(response.body)
207
+ res.client = self if !res.nil?
212
208
  $LOG.warn "Expected #{klass} but got #{res.class}" if res.class!=klass
213
209
  rescue Exception => e
214
210
  $LOG.error "Failed to parse #{format} as resource #{klass}: #{e.message} %n #{e.backtrace.join("\n")} #{response}"
215
211
  nil
216
212
  end
217
- res.client = self
218
213
  res
219
214
  end
220
215
 
@@ -226,7 +221,7 @@ module FHIR
226
221
  if [:get, :delete, :head].include?(request['method'])
227
222
  method(request['method']).call(request['url'], request['headers'])
228
223
  elsif [:post, :put].include?(request['method'])
229
- resource = request['headers']['resource'].constantize.from_xml(request['payload'])
224
+ resource = FHIR.from_contents(request['payload']) unless request['payload'].nil?
230
225
  method(request['method']).call(request['url'], resource, request['headers'])
231
226
  end
232
227
  end
@@ -295,7 +290,7 @@ module FHIR
295
290
 
296
291
  def get(path, headers)
297
292
  url = URI(build_url(path)).to_s
298
- puts "GETTING: #{url}"
293
+ $LOG.info "GETTING: #{url}"
299
294
  headers = clean_headers(headers)
300
295
  if @use_oauth2_auth
301
296
  # @client.refresh!
@@ -320,22 +315,28 @@ module FHIR
320
315
  @reply = FHIR::ClientReply.new(req, res)
321
316
  else
322
317
  headers.merge!(@security_headers) if @use_basic_auth
323
- @client.get(url, headers){ |response, request, result|
324
- $LOG.info "GET - Request: #{request.to_json}, Response: #{response.force_encoding("UTF-8")}"
325
- request.args[:path] = url.gsub(@baseServiceUrl,'')
326
- res = {
327
- :code => result.code,
328
- :headers => scrubbed_response_headers(result.each_key{}),
329
- :body => response
330
- }
331
- @reply = FHIR::ClientReply.new(request.args, res)
318
+ begin
319
+ response = @client.get(url, headers)
320
+ rescue Exception => e
321
+ response = e.response if e.response
322
+ end
323
+
324
+ $LOG.info "GET - Request: #{response.request.to_json}, Response: #{response.body.force_encoding("UTF-8")}"
325
+ response.request.args[:path] = response.request.args[:url].gsub(@baseServiceUrl,'')
326
+ headers = response.headers.inject({}){ |h,(k,v)| h[k.to_s.gsub('_','-')] = v.to_s; h}
327
+ res = {
328
+ :code => response.code,
329
+ :headers => scrubbed_response_headers(headers),
330
+ :body => response.body
332
331
  }
332
+
333
+ @reply = FHIR::ClientReply.new(response.request.args, res)
333
334
  end
334
335
  end
335
336
 
336
337
  def post(path, resource, headers)
337
338
  url = URI(build_url(path)).to_s
338
- puts "POSTING: #{url}"
339
+ $LOG.info "POSTING: #{url}"
339
340
  headers = clean_headers(headers)
340
341
  payload = request_payload(resource, headers) if resource
341
342
  if @use_oauth2_auth
@@ -376,7 +377,7 @@ module FHIR
376
377
 
377
378
  def put(path, resource, headers)
378
379
  url = URI(build_url(path)).to_s
379
- puts "PUTTING: #{url}"
380
+ $LOG.info "PUTTING: #{url}"
380
381
  headers = clean_headers(headers)
381
382
  payload = request_payload(resource, headers) if resource
382
383
  if @use_oauth2_auth
@@ -417,7 +418,7 @@ module FHIR
417
418
 
418
419
  def patch(path, patchset, headers)
419
420
  url = URI(build_url(path)).to_s
420
- puts "PATCHING: #{url}"
421
+ $LOG.info "PATCHING: #{url}"
421
422
  headers = clean_headers(headers)
422
423
  payload = request_patch_payload(patchset, headers['format'])
423
424
  if @use_oauth2_auth
@@ -459,7 +460,7 @@ module FHIR
459
460
 
460
461
  def delete(path, headers)
461
462
  url = URI(build_url(path)).to_s
462
- puts "DELETING: #{url}"
463
+ $LOG.info "DELETING: #{url}"
463
464
  headers = clean_headers(headers)
464
465
  if @use_oauth2_auth
465
466
  # @client.refresh!
@@ -500,7 +501,7 @@ module FHIR
500
501
  def head(path, headers)
501
502
  headers.merge!(@security_headers) unless @security_headers.blank?
502
503
  url = URI(build_url(path)).to_s
503
- puts "HEADING: #{url}"
504
+ $LOG.info "HEADING: #{url}"
504
505
  RestClient.head(url, headers){ |response, request, result|
505
506
  $LOG.info "HEAD - Request: #{request.to_json}, Response: #{response.force_encoding("UTF-8")}"
506
507
  request.args[:path] = url.gsub(@baseServiceUrl,'')
data/lib/ext/model.rb CHANGED
@@ -22,46 +22,85 @@ module FHIR
22
22
  end
23
23
 
24
24
  def self.read(id, client = self.client)
25
- client.read(self, id).resource
25
+ handle_response client.read(self, id)
26
26
  end
27
27
 
28
28
  def self.read_with_summary(id, summary, client = self.client)
29
- client.read(self, id, client.default_format, summary).resource
29
+ handle_response client.read(self, id, client.default_format, summary)
30
+ end
31
+
32
+ def self.vread(id, version_id, client = self.client)
33
+ handle_response client.vread(self, id, version_id)
34
+ end
35
+
36
+ def self.resource_history(client = self.client)
37
+ handle_response client.resource_history(self)
38
+ end
39
+
40
+ def self.resource_history_as_of(last_update)
41
+ handle_response client.resource_history_as_of(self, last_update)
42
+ end
43
+
44
+ def self.resource_instance_history(id, client = self.client)
45
+ handle_response client.resource_instance_history(self, id)
46
+ end
47
+
48
+ def self.resource_instance_history_as_of(id, last_update, client = self.client)
49
+ handle_response client.resource_instance_history_as_of(self, id, last_update)
30
50
  end
31
51
 
32
52
  def self.search(params = {}, client = self.client)
33
- client.search(self, search: { parameters: params }).resource
53
+ handle_response client.search(self, search: { parameters: params })
34
54
  end
35
55
 
36
56
  def self.create(model, client = self.client)
37
57
  model = new(model) unless model.is_a?(self)
38
- client.create(model).resource
58
+ handle_response client.create(model)
39
59
  end
40
60
 
41
61
  def self.conditional_create(model, params, client = self.client)
42
62
  model = new(model) unless model.is_a?(self)
43
- client.conditional_create(model, params)
63
+ handle_response client.conditional_create(model, params)
64
+ end
65
+
66
+ def self.all
67
+ handle_response client.read_feed(self)
68
+ end
69
+
70
+ def vread(version_id)
71
+ self.class.vread(id, version_id, client)
44
72
  end
45
73
 
46
74
  def create
47
- client.create(self).resource
75
+ handle_response client.create(self)
48
76
  end
49
77
 
50
78
  def conditional_create(params)
51
- client.conditional_create(self, params)
79
+ handle_response client.conditional_create(self, params)
52
80
  end
53
81
 
54
82
  def update
55
- client.update(self, id).resource
83
+ handle_response client.update(self, id)
56
84
  end
57
85
 
58
86
  def conditional_update(params)
59
- client.conditional_update(self, self.id, params).resource
87
+ handle_response client.conditional_update(self, self.id, params)
60
88
  end
61
89
 
62
90
  def destroy
63
- client.destroy(self.class, id) unless id.nil?
91
+ handle_response client.destroy(self.class, id) unless id.nil?
64
92
  nil
65
93
  end
94
+
95
+ private
96
+
97
+ def self.handle_response(response)
98
+ raise ClientException.new "Server returned #{response.code}.", response if response.code.between?(400,599)
99
+ response.resource
100
+ end
101
+
102
+ def handle_response(response)
103
+ self.class.handle_response(response)
104
+ end
66
105
  end
67
106
  end
data/lib/ext/reference.rb CHANGED
@@ -5,7 +5,7 @@ module FHIR
5
5
  type, id = reference.to_s.split("/")
6
6
  return unless [type, id].all?(&:present?)
7
7
  klass = "FHIR::#{type}".constantize
8
- klass.read(client, id)
8
+ klass.read(id, client)
9
9
  end
10
10
  end
11
11
  end
data/lib/fhir_client.rb CHANGED
@@ -28,4 +28,4 @@ require_relative File.join('.','feed_format.rb')
28
28
  require_relative File.join('.','patch_format.rb')
29
29
  require_relative File.join('.','model','client_reply.rb')
30
30
  require_relative File.join('.','model','tag.rb')
31
-
31
+ require_relative File.join('.','client_exception.rb')
@@ -70,6 +70,8 @@ module FHIR
70
70
  url += "/$lookup"
71
71
  elsif (opr && opr[:name]== :concept_map_translate)
72
72
  url += "/$translate"
73
+ elsif (opr && opr[:name]== :closure_table_maintenance)
74
+ url += "/$closure"
73
75
  end
74
76
  end
75
77
 
@@ -77,13 +77,20 @@ module FHIR
77
77
  terminology_operation(options, format)
78
78
  end
79
79
 
80
- #
80
+ # ConceptMap Translation
81
81
  def concept_map_translate(params={}, format=@default_format)
82
82
  options = { resource: FHIR::ConceptMap, operation: { name: :concept_map_translate } }
83
83
  options.deep_merge!(params)
84
84
  terminology_operation(options, format)
85
85
  end
86
86
 
87
+ # ConceptMap Closure Table Maintenance
88
+ def closure_table_maintenance(params={}, format=@default_format)
89
+ options = { operation: { name: :closure_table_maintenance } }
90
+ options.deep_merge!(params)
91
+ terminology_operation(options, format)
92
+ end
93
+
87
94
  def terminology_operation(params={}, format=@default_format)
88
95
  options = { format: format }
89
96
  # params = [id, code, system, version, display, coding, codeableConcept, date, abstract]
data/lib/tasks/tasks.rake CHANGED
@@ -36,12 +36,15 @@ namespace :fhir do
36
36
  end
37
37
 
38
38
  desc 'count all resources for a given server'
39
- task :count, [:url] do |t, args|
39
+ task :count, [:url,:display_zero] do |t, args|
40
40
  client = FHIR::Client.new(args.url)
41
+ display_zero = (args.display_zero == 'true')
41
42
  counts = {}
42
- fhir_resources.map do | klass |
43
+ fhir_resources.each do | klass |
43
44
  reply = client.read_feed(klass)
44
- counts["#{klass.name.demodulize}"] = reply.resource.total unless reply.resource.nil?
45
+ if !reply.resource.nil? && (reply.resource.total > 0 || display_zero)
46
+ counts["#{klass.name.demodulize}"] = reply.resource.total
47
+ end
45
48
  end
46
49
  printf " %-30s %5s\n", 'Resource', 'Count'
47
50
  printf " %-30s %5s\n", '--------', '-----'
@@ -54,7 +57,7 @@ namespace :fhir do
54
57
  desc 'delete all resources for a given server'
55
58
  task :clean, [:url] do |t, args|
56
59
  client = FHIR::Client.new(args.url)
57
- fhir_resources.map do | klass |
60
+ fhir_resources.each do | klass |
58
61
  reply = client.read_feed(klass)
59
62
  while !reply.nil? && !reply.resource.nil? && reply.resource.total > 0
60
63
  reply.resource.entry.each do |entry|
@@ -67,7 +70,7 @@ namespace :fhir do
67
70
  end
68
71
 
69
72
  def fhir_resources
70
- Mongoid.models.select {|c| c.name.include?('FHIR') && !c.included_modules.find_index(FHIR::Resource).nil?}
73
+ FHIR::RESOURCES.map {|r| Object::const_get("FHIR::#{r}")}
71
74
  end
72
75
 
73
76
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fhir_client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andre Quina
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2016-06-10 00:00:00.000000000 Z
13
+ date: 2016-08-12 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: fhir_models
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 0.3.1
21
+ version: 1.6.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - '>='
27
27
  - !ruby/object:Gem::Version
28
- version: 0.3.1
28
+ version: 1.6.0
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: tilt
31
31
  requirement: !ruby/object:Gem::Requirement
@@ -124,6 +124,7 @@ files:
124
124
  - README.md
125
125
  - Rakefile
126
126
  - fhir_client.gemspec
127
+ - lib/client_exception.rb
127
128
  - lib/client_interface.rb
128
129
  - lib/ext/bundle.rb
129
130
  - lib/ext/model.rb
@@ -172,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
172
173
  version: '0'
173
174
  requirements: []
174
175
  rubyforge_project:
175
- rubygems_version: 2.4.6
176
+ rubygems_version: 2.0.14.1
176
177
  signing_key:
177
178
  specification_version: 4
178
179
  summary: A Gem for handling FHIR client requests in ruby