fhir_client 3.0.2 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +11 -1147
- data/Gemfile +1 -1
- data/README.md +31 -2
- data/fhir_client.gemspec +2 -1
- data/lib/fhir_client.rb +1 -0
- data/lib/fhir_client/client.rb +160 -38
- data/lib/fhir_client/ext/bundle.rb +25 -5
- data/lib/fhir_client/ext/model.rb +104 -79
- data/lib/fhir_client/ext/reference.rb +24 -5
- data/lib/fhir_client/fhir_api_validation.json +1 -1
- data/lib/fhir_client/model/client_reply.rb +20 -4
- data/lib/fhir_client/resource_address.rb +2 -0
- data/lib/fhir_client/sections/crud.rb +17 -11
- data/lib/fhir_client/sections/history.rb +2 -1
- data/lib/fhir_client/sections/operations.rb +22 -17
- data/lib/fhir_client/sections/transactions.rb +7 -7
- data/lib/fhir_client/tasks/tasks.rake +1 -1
- data/lib/fhir_client/version.rb +1 -1
- metadata +18 -4
@@ -1,5 +1,5 @@
|
|
1
1
|
module FHIR
|
2
|
-
|
2
|
+
module BundleExtras
|
3
3
|
def self_link
|
4
4
|
link.select { |n| n.relation == 'self' }.first
|
5
5
|
end
|
@@ -28,15 +28,35 @@ module FHIR
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def each(&block)
|
31
|
-
|
32
|
-
|
33
|
-
|
31
|
+
iterator = @entry.map(&:resource).each(&block)
|
32
|
+
if next_bundle
|
33
|
+
next_iterator = next_bundle.each(&block)
|
34
|
+
Enumerator.new do |y|
|
35
|
+
iterator.each { |r| y << r }
|
36
|
+
next_iterator.each { |r| y << r }
|
37
|
+
end
|
38
|
+
else
|
39
|
+
iterator
|
40
|
+
end
|
34
41
|
end
|
35
42
|
|
36
43
|
def next_bundle
|
37
|
-
# TODO: test this
|
38
44
|
return nil unless client && next_link.try(:url)
|
39
45
|
@next_bundle ||= client.parse_reply(self.class, client.default_format, client.raw_read_url(next_link.url))
|
40
46
|
end
|
41
47
|
end
|
42
48
|
end
|
49
|
+
|
50
|
+
module FHIR
|
51
|
+
class Bundle
|
52
|
+
include FHIR::BundleExtras
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
module FHIR
|
57
|
+
module DSTU2
|
58
|
+
class Bundle
|
59
|
+
include FHIR::BundleExtras
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -1,112 +1,137 @@
|
|
1
1
|
module FHIR
|
2
|
-
|
3
|
-
cattr_accessor :client, instance_accessor: false
|
2
|
+
module ModelExtras
|
4
3
|
|
5
|
-
def
|
6
|
-
|
4
|
+
def self.included base
|
5
|
+
base.send :include, InstanceMethods
|
6
|
+
base.extend ClassMethods
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
module InstanceMethods
|
10
|
+
def client
|
11
|
+
FHIR::Model.client
|
12
|
+
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
Array.wrap(values).each do |value|
|
15
|
-
next unless value.is_a?(FHIR::Model)
|
16
|
-
next if value.client == client
|
17
|
-
value.client = client
|
18
|
-
end
|
14
|
+
def client=(client)
|
15
|
+
FHIR::Model.client = client
|
19
16
|
end
|
20
|
-
end
|
21
17
|
|
22
|
-
|
23
|
-
|
24
|
-
|
18
|
+
def vread(version_id)
|
19
|
+
self.class.vread(id, version_id, client)
|
20
|
+
end
|
25
21
|
|
26
|
-
|
27
|
-
|
28
|
-
|
22
|
+
def create
|
23
|
+
handle_response client.create(self)
|
24
|
+
end
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
def conditional_create(params)
|
27
|
+
handle_response client.conditional_create(self, params)
|
28
|
+
end
|
33
29
|
|
34
|
-
|
35
|
-
|
36
|
-
|
30
|
+
def update
|
31
|
+
handle_response client.update(self, id)
|
32
|
+
end
|
37
33
|
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
def conditional_update(params)
|
35
|
+
handle_response client.conditional_update(self, id, params)
|
36
|
+
end
|
41
37
|
|
42
|
-
|
43
|
-
|
44
|
-
|
38
|
+
def destroy
|
39
|
+
handle_response client.destroy(self.class, id) unless id.nil?
|
40
|
+
nil
|
41
|
+
end
|
45
42
|
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
def resolve(reference)
|
44
|
+
if reference.contained?
|
45
|
+
contained.detect { |c| c.id == reference.id }
|
46
|
+
else
|
47
|
+
reference.read
|
48
|
+
end
|
49
|
+
end
|
49
50
|
|
50
|
-
|
51
|
-
handle_response
|
51
|
+
private
|
52
|
+
def handle_response(response)
|
53
|
+
raise ClientException.new "Server returned #{response.code}.", response if response.code.between?(400, 599)
|
54
|
+
response.resource
|
55
|
+
end
|
52
56
|
end
|
53
57
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
+
module ClassMethods
|
59
|
+
|
60
|
+
def client
|
61
|
+
FHIR::Model.client
|
62
|
+
end
|
58
63
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
64
|
+
def client=(client)
|
65
|
+
FHIR::Model.client = client
|
66
|
+
end
|
63
67
|
|
64
|
-
|
65
|
-
|
66
|
-
|
68
|
+
def read(id, client = self.client)
|
69
|
+
handle_response client.read(self, id)
|
70
|
+
end
|
67
71
|
|
68
|
-
|
69
|
-
|
70
|
-
|
72
|
+
def read_with_summary(id, summary, client = self.client)
|
73
|
+
handle_response client.read(self, id, client.default_format, summary)
|
74
|
+
end
|
71
75
|
|
72
|
-
|
73
|
-
|
74
|
-
|
76
|
+
def vread(id, version_id, client = self.client)
|
77
|
+
handle_response client.vread(self, id, version_id)
|
78
|
+
end
|
75
79
|
|
76
|
-
|
77
|
-
|
78
|
-
|
80
|
+
def resource_history(client = self.client)
|
81
|
+
handle_response client.resource_history(self)
|
82
|
+
end
|
79
83
|
|
80
|
-
|
81
|
-
|
82
|
-
|
84
|
+
def resource_history_as_of(last_update, client = self.client)
|
85
|
+
handle_response client.resource_history_as_of(self, last_update)
|
86
|
+
end
|
83
87
|
|
84
|
-
|
85
|
-
|
86
|
-
|
88
|
+
def resource_instance_history(id, client = self.client)
|
89
|
+
handle_response client.resource_instance_history(self, id)
|
90
|
+
end
|
87
91
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
92
|
+
def resource_instance_history_as_of(id, last_update, client = self.client)
|
93
|
+
handle_response client.resource_instance_history_as_of(self, id, last_update)
|
94
|
+
end
|
92
95
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
96
|
+
def search(params = {}, client = self.client)
|
97
|
+
handle_response client.search(self, search: { parameters: params })
|
98
|
+
end
|
99
|
+
|
100
|
+
def create(model, client = self.client)
|
101
|
+
model = new(model) unless model.is_a?(self)
|
102
|
+
handle_response client.create(model)
|
98
103
|
end
|
99
|
-
end
|
100
104
|
|
101
|
-
|
105
|
+
def conditional_create(model, params, client = self.client)
|
106
|
+
model = new(model) unless model.is_a?(self)
|
107
|
+
handle_response client.conditional_create(model, params)
|
108
|
+
end
|
109
|
+
|
110
|
+
def all(client = self.client)
|
111
|
+
handle_response client.read_feed(self)
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
102
115
|
|
103
|
-
|
104
|
-
|
105
|
-
|
116
|
+
def handle_response(response)
|
117
|
+
raise ClientException.new "Server returned #{response.code}.", response if response.code.between?(400, 599)
|
118
|
+
response.resource
|
119
|
+
end
|
106
120
|
end
|
121
|
+
end
|
122
|
+
end
|
107
123
|
|
108
|
-
|
109
|
-
|
124
|
+
module FHIR
|
125
|
+
class Model
|
126
|
+
include FHIR::ModelExtras
|
127
|
+
cattr_accessor :client, instance_accessor: false
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
module FHIR
|
132
|
+
module DSTU2
|
133
|
+
class Model
|
134
|
+
include FHIR::ModelExtras
|
110
135
|
end
|
111
136
|
end
|
112
137
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module FHIR
|
2
|
-
|
2
|
+
module ReferenceExtras
|
3
3
|
def contained?
|
4
4
|
reference.to_s.start_with?('#')
|
5
5
|
end
|
6
6
|
|
7
|
-
def
|
7
|
+
def reference_id
|
8
8
|
if contained?
|
9
9
|
reference.to_s[1..-1]
|
10
10
|
else
|
@@ -16,13 +16,32 @@ module FHIR
|
|
16
16
|
reference.to_s.split('/').first unless contained?
|
17
17
|
end
|
18
18
|
|
19
|
+
def read
|
20
|
+
return if contained? || type.blank? || (id.blank? && reference.blank?)
|
21
|
+
rid = id || reference_id
|
22
|
+
resource_class.read(rid, client)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
module FHIR
|
28
|
+
class Reference
|
29
|
+
include FHIR::ReferenceExtras
|
30
|
+
|
19
31
|
def resource_class
|
20
32
|
"FHIR::#{type}".constantize unless contained?
|
21
33
|
end
|
34
|
+
end
|
35
|
+
end
|
22
36
|
|
23
|
-
|
24
|
-
|
25
|
-
|
37
|
+
module FHIR
|
38
|
+
module DSTU2
|
39
|
+
class Reference
|
40
|
+
include FHIR::ReferenceExtras
|
41
|
+
|
42
|
+
def resource_class
|
43
|
+
"FHIR::DSTU2::#{type}".constantize unless contained?
|
44
|
+
end
|
26
45
|
end
|
27
46
|
end
|
28
47
|
end
|
@@ -46,10 +46,13 @@ module FHIR
|
|
46
46
|
attr_accessor :response
|
47
47
|
attr_accessor :resource # a FHIR resource
|
48
48
|
attr_accessor :resource_class # class of the :resource
|
49
|
+
attr_accessor :fhir_version
|
49
50
|
|
50
|
-
def initialize(request, response)
|
51
|
+
def initialize(request, response, client)
|
51
52
|
@request = request
|
52
53
|
@response = response
|
54
|
+
@fhir_version = :stu3
|
55
|
+
@fhir_version = client.fhir_version
|
53
56
|
end
|
54
57
|
|
55
58
|
def code
|
@@ -154,10 +157,14 @@ module FHIR
|
|
154
157
|
if body_rules['types']
|
155
158
|
body_type_match = false
|
156
159
|
begin
|
157
|
-
content =
|
160
|
+
content = if @fhir_version == :stu3
|
161
|
+
FHIR.from_contents(body)
|
162
|
+
else
|
163
|
+
FHIR::DSTU2.from_contents(body)
|
164
|
+
end
|
158
165
|
body_rules['types'].each do |type|
|
159
166
|
body_type_match = true if content.resourceType == type
|
160
|
-
body_type_match = true if type == 'Resource' &&
|
167
|
+
body_type_match = true if type == 'Resource' && validate_resource(content.resourceType)
|
161
168
|
end
|
162
169
|
rescue
|
163
170
|
FHIR.logger.warn "ClientReply was unable to validate response body: #{body}"
|
@@ -174,6 +181,15 @@ module FHIR
|
|
174
181
|
errors
|
175
182
|
end
|
176
183
|
|
177
|
-
|
184
|
+
def validate_resource(resource_type)
|
185
|
+
if @fhir_version == :stu3
|
186
|
+
return true if FHIR::RESOURCES.include?(resource_type)
|
187
|
+
else
|
188
|
+
return true if FHIR::DSTU2::RESOURCES.include?(resource_type)
|
189
|
+
end
|
190
|
+
false
|
191
|
+
end
|
192
|
+
|
193
|
+
private :validate_headers, :validate_body, :validate_resource
|
178
194
|
end
|
179
195
|
end
|
@@ -40,6 +40,8 @@ module FHIR
|
|
40
40
|
|
41
41
|
fhir_headers.merge!(options) unless options.empty?
|
42
42
|
fhir_headers[:operation] = options[:operation][:name] if options[:operation] && options[:operation][:name]
|
43
|
+
fhir_headers.delete('id')
|
44
|
+
fhir_headers.delete('resource')
|
43
45
|
fhir_headers
|
44
46
|
end
|
45
47
|
|
@@ -36,13 +36,11 @@ module FHIR
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def raw_read(options)
|
39
|
-
|
40
|
-
reply.body
|
39
|
+
get resource_url(options), fhir_headers(options)
|
41
40
|
end
|
42
41
|
|
43
|
-
def raw_read_url(url)
|
44
|
-
|
45
|
-
reply.body
|
42
|
+
def raw_read_url(url, format = @default_format)
|
43
|
+
get url, fhir_headers(format: format)
|
46
44
|
end
|
47
45
|
|
48
46
|
#
|
@@ -89,10 +87,10 @@ module FHIR
|
|
89
87
|
def partial_update(klass, id, patchset, options = {}, format = @default_format)
|
90
88
|
options = { resource: klass, id: id, format: format }.merge options
|
91
89
|
|
92
|
-
if
|
90
|
+
if [FHIR::Formats::ResourceFormat::RESOURCE_XML, FHIR::Formats::ResourceFormat::RESOURCE_XML_DSTU2].include?(format)
|
93
91
|
options[:format] = FHIR::Formats::PatchFormat::PATCH_XML
|
94
92
|
options[:Accept] = format
|
95
|
-
elsif
|
93
|
+
elsif [FHIR::Formats::ResourceFormat::RESOURCE_JSON, FHIR::Formats::ResourceFormat::RESOURCE_JSON_DSTU2].include?(format)
|
96
94
|
options[:format] = FHIR::Formats::PatchFormat::PATCH_JSON
|
97
95
|
options[:Accept] = format
|
98
96
|
end
|
@@ -119,8 +117,8 @@ module FHIR
|
|
119
117
|
# Create a new resource with a server assigned id. Return the newly created
|
120
118
|
# resource with the id the server assigned.
|
121
119
|
#
|
122
|
-
def create(resource, format = @default_format)
|
123
|
-
base_create(resource,
|
120
|
+
def create(resource, options = {}, format = @default_format)
|
121
|
+
base_create(resource, options, format)
|
124
122
|
end
|
125
123
|
|
126
124
|
#
|
@@ -150,9 +148,17 @@ module FHIR
|
|
150
148
|
type = reply.response[:headers].detect{|x, _y| x.downcase=='content-type'}.try(:last)
|
151
149
|
if !type.nil?
|
152
150
|
reply.resource = if type.include?('xml') && !reply.body.empty?
|
153
|
-
|
151
|
+
if @fhir_version == :stu3
|
152
|
+
FHIR::Xml.from_xml(reply.body)
|
153
|
+
else
|
154
|
+
FHIR::DSTU2::Xml.from_xml(reply.body)
|
155
|
+
end
|
154
156
|
elsif type.include?('json') && !reply.body.empty?
|
155
|
-
|
157
|
+
if @fhir_version == :stu3
|
158
|
+
FHIR::Json.from_json(reply.body)
|
159
|
+
else
|
160
|
+
FHIR::DSTU2::Json.from_json(reply.body)
|
161
|
+
end
|
156
162
|
else
|
157
163
|
resource # just send back the submitted resource
|
158
164
|
end
|
@@ -24,8 +24,9 @@ module FHIR
|
|
24
24
|
# public <T extends Resource> AtomFeed history(DateAndTime last_update, Class<T> resourceClass, String id);
|
25
25
|
|
26
26
|
def history(options)
|
27
|
+
options = {format: @default_format}.merge(options)
|
27
28
|
reply = get resource_url(options), fhir_headers(options).except(:history)
|
28
|
-
reply.resource = parse_reply(options[:resource],
|
29
|
+
reply.resource = parse_reply(options[:resource], options[:format], reply)
|
29
30
|
reply.resource_class = options[:resource]
|
30
31
|
reply
|
31
32
|
end
|