-
Notifications
You must be signed in to change notification settings - Fork 61
FHIR Client API Design Ideas
A lot of our current code centers around the idea of fetching data about a particular patient. Our FHIR-request wrapping code has encapsulated this nicely already, and as we're looking at using fhir_client
, we're realizing it doesn't support most of this.
For example, what if we want to get all observations related to a patient from the past week? Currently, with fhir_client
, we might have to do something like this:
patient_response = client.read(FHIR::Patient, patient_id)
patient = patient_response.resource
observation_response = client.search(FHIR::Observation, search: {
parameters: {
patient: patient.id,
date: ">#{1.week.ago.to_date}"
}
})
observations = observation_response.resource.entry.map(&:resource)
However, following the pattern of libraries like ActiveRecord, it would be nice to be able to do something like this:
patient = client.find(FHIR::Patient, patient_id)
observations = patient.observations(date: ">#{1.week.ago.to_date}")
Where the FHIR::Patient
instance could remember the client it was fetched from, and could also be aware of associations and use that client to fetch them.
Or -- we could take the ActiveRecord analogy further, and do something like this:
FHIR::Base.client = client
patient = FHIR::Patient.find(patient_id)
observations = patient.observations(date: ">#{1.week.ago.to_date}")
conditions = patient.conditions
Alternatively, maybe auto-defining instance methods on FHIR::Patient
would be tricky, and it would make more sense to do something like:
patient = FHIR::Patient.read(client, patient_id)
observations = FHIR::Observation.search(client, patient: patient, date: { gt: 1.week.ago })
conditions = FHIR::Condition.search(client, patient: patient)
To make this work in a very basic way, we could do:
module FHIR::Utilities
module ClassMethods
def error_for(bad_response)
# figure out what errors to raise based on the response
end
def read(client, id)
reply = client.read(self, id)
reply.resource || raise error_for(reply.response)
end
def search(client, params)
# potentially do some modification of params based on search param introspection
reply = client.search(self, search: { parameters: params })
raise error_for(reply.response) unless reply.resource
reply.resource.entry.map(&:resource)
end
end
def self.included(base)
super
base.extend(ClassMethods)
end
end
###Comments from Rob
We like your idea of using ActiveRecord-style interface. In order for it to be useful to our Crucible test system, we would need access to the actual response as well. In your examples, would it make sense to expose it as an attribute, like
patient.response
,observations.response
, etc? Or maybe we should store it in the client, like inclient.last_response
? What do you think make sense?
For searches, we may need to keep the return type as Bundle (instead of an array), because it is possible for bundles to be paginated. Would it be possible to have Bundle be enumerable, but have the next pages be fetched in a lazy fashion? See https://www.hl7.org/fhir/http.html#paging
Doing something like
observations = patient.observations(..)
might be a bit difficult for us right now, because I’m not sure if we have easy access to that relationship (that observations support a search named “patient” that searches over the Patient resource) when we are generating resources. We’d have to look into that. I think we can start by doingobservation = FHIR::Observation.search(…)
, since we’d want to support that method of searching anyhow, and then look into figuring out how to automatically add supported search methods directly to the instances later.
I like not having to pass client in with each call as well, as it gets pretty redundant… though
FHIR::Base.client = client
isn’t particularly intuitive. I’m not sure if we have a much better solution though, maybe have it be a ‘configure’ method that accepts a client (among potentially other things)?
- Getting Started
- Configuration
-
Searching
- History
- CRUD
- Transactions
- Validation
-
Operations
$everything
$validate