A Rails 7 application styled with Tailwind CSS that interacts with a FHIR server to fetch and display patient information.
PseudoEHR is a reference implementation client application for the PACIO Project use cases. It supports the following PACIO Implementation Guides:
- PACIO Advance Directive Interoperability (ADI)
- PACIO Personal Functioning and Engagement (PFE)
- PACIO Transitions of Care (TOC)
- Standardized Medication Profile (SMP)
- Features
- Supported FHIR Resources
- Prerequisites
- Technologies Used
- Installation
- Docker Compose Deployment
- Usage
- Application Structure
- Testing
- Common Commands
- Contributing
- License
- FHIR Server Integration: Connects to FHIR servers to fetch and cache patient details.
- Patient Display: Shows a list of patients and individual patient details.
- Server Authentication: Handles FHIR servers that require SMART-on-FHIR App Launch for Symmetric Client Auth.
- Sample Data Management: Browse and view sample FHIR resources organized by use case and scene, and load them into FHIR servers.
- QuestionnaireResponse Transformation: Convert QuestionnaireResponse into PFE Observation Bundles.
The application is able to query (read/search) and display the following FHIR resources:
- CareTeam
- Composition
- Condition
- DetectedIssue
- DiagnosticReport
- DocumentReference
- Goal
- List (Medication)
- Location
- MedicationRequest
- NutritionOrder
- Observation
- Organization
- Patient
- PractitionerRole
- Procedure
- QuestionnaireResponse
- ServiceRequest
All searches are performed using the _include=* parameter to retrieve and include related resources.
- Ruby version 3.3.6
- Rails 7
- PostgreSQL
- Ruby on Rails 7: The main web framework.
- Turbo: Part of the Hotwire stack used for making real-time page updates without needing JavaScript.
- Stimulus: A JavaScript framework that augments HTML with behavior using simple, declarative attributes.
- Tailwind CSS: Used for styling the UI.
- FHIR Integration: For interacting with FHIR servers, focusing on patient data.
- PostgreSQL: The relational database used.
- RSpec: Testing framework for unit and feature tests.
Make sure to start PostgreSQL before running the server.
-
Clone the Repository
git clone https://github.com/paciowg/pseudo-ehr.git cd pseudo-ehr -
Install Dependencies
yarn install bundle install
Note: Building tailwind may require BUNDLE_FORCE_RUBY_PLATFORM to be unset, see https://github.com/flavorjones/tailwindcss-ruby#check-bundle_force_ruby_platform.
-
Database Setup
bundle exec rails db:create bundle exec rails db:migrate bundle exec rails db:seed
Note: This should only be executed the first time you clone this repository.
rails db:seedwill persist the default servers commonly used in PACIO tracks and this app has been tested against
This application can be deployed using Docker Compose for a simple setup.
-
Environment Setup
You need a
SECRET_KEY_BASEfor Rails to run in production. You can generate a key with Rails:bundle exec rails secretYour
.envfile (create one if needed) should contain the generated secret key and a password for the database:# .env SECRET_KEY_BASE=your_generated_secret_key_here POSTGRES_PASSWORD=your_secure_password -
Build and Start Services
Build the Docker image and start the application and database services:
docker compose up --build -d
-
Database Setup
With the services running, set up the database. This command runs inside the application container.
docker compose run --rm app rails db:setup
This will create, migrate, and seed the database.
-
Accessing the Application
The application will be available at
http://localhost. (It maps to port 80 on your host). -
Managing the Services
- To view the application logs:
docker compose logs -f app
- To stop the services:
docker compose down
- To view the application logs:
-
Starting the Server
./bin/dev
Open your browser and navigate to
http://localhost:3000. -
Connecting to a FHIR Server
- Navigate to the root path.
- Select a FHIR server from the list of saved servers or enter your FHIR server details and connect.
- Once connected, you can view a list of patients or see details of a specific patient.
This app has been tested with the following FHIR servers:
| Server Name | Base URL | Tested IGs |
|---|---|---|
| PACIO Sandbox | https://gw.interop.community/paciosandbox/open |
PFE, SMP, TOC |
| Michigan Health Information Network (MiHIN) | https://gw.interop.community/MiHIN/open |
PFE, SMP, TOC |
| MaxMD FHIR Server | https://qa-rr-fhir2.maxmddirect.com |
ADI |
The Pseudo-EHR application follows the standard Rails structure with a few custom directories:
-
app/: Contains the core logic of the app including models, views, controllers, and services.
- controllers/: Handles the request-response cycle.
- models/: Contains business logic and data manipulation methods.
- views/: Templates for rendering HTML responses.
- services/: Custom service classes for managing FHIR integration and other core functionalities.
-
config/: Configuration files for the Rails application, including routes, initializers, and environment settings.
-
db/: Manages the database schema, migrations, and seeds.
-
lib/: Contains custom libraries and modules used throughout the app.
-
spec/: RSpec tests for unit and integration testing.
-
public/: Static assets and compiled files.
The application provides an API endpoint for processing QuestionnaireResponses and converting them to PFE Observations.
Endpoint: POST /api/convert_qr_to_pfe_and_submit
Description: Processes a FHIR QuestionnaireResponse resource, converts it into PFE Observations according to the PACIO PFE Implementation Guide, and submits the results to a specified FHIR server.
Parameters:
questionnaire_response: A FHIR QuestionnaireResponse resource (required)fhir_server: The base URL of the FHIR server to submit the results to (required)
Response:
- Success (200 OK): Returns the FHIR transaction bundle containing the created resources
- Error (400 Bad Request): Returns an error message if the parameters are invalid
- Error (422 Unprocessable Entity): Returns an error message if the conversion or submission fails
Example Request:
{
"questionnaire_response": {
"resourceType": "QuestionnaireResponse",
"id": "example-qr",
"status": "completed",
"subject": {
"reference": "Patient/example"
},
"questionnaire": "http://example.org/Questionnaire/example",
"item": [
{
"linkId": "1",
"text": "Example question",
"answer": [
{
"valueString": "Example answer"
}
]
}
]
},
"fhir_server": "https://example.org/fhir"
}Example Success Response:
{
"success?": true,
"code": 200,
"resource": {
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"resource": {
"resourceType": "QuestionnaireResponse",
"id": "example-qr",
"status": "completed",
"subject": {
"reference": "Patient/example"
},
"questionnaire": "http://example.org/Questionnaire/example",
"item": [
{
"linkId": "1",
"text": "Example question",
"answer": [
{
"valueString": "Example answer"
}
]
}
]
},
"request": {
"method": "PUT",
"url": "QuestionnaireResponse/example-qr"
}
},
{
"resource": {
"resourceType": "Observation",
"id": "example-qr-1",
"status": "final",
"category": [
{
"coding": [
{
"system": "http://hl7.org/fhir/us/pacio-pfe/CodeSystem/pfe-survey-category-cs",
"code": "survey"
}
]
},
{
"coding": [
{
"system": "http://hl7.org/fhir/us/core/CodeSystem/us-core-category",
"code": "functional-status",
"display": "Functional Status"
}
]
}
],
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "1",
"display": "Example question"
}
]
},
"subject": {
"reference": "Patient/example"
},
"valueString": "Example answer",
"derivedFrom": [
{
"reference": "QuestionnaireResponse/example-qr"
}
]
},
"request": {
"method": "PUT",
"url": "Observation/example-qr-1"
}
}
]
}
}
The application provides functionality to convert FHIR QuestionnaireResponse resources into PACIO Personal Functioning and Engagement (PFE) Observations. This conversion can be performed through both the UI and the API.
The UI provides a user-friendly way to convert QuestionnaireResponses to PFE Observations:
-
View QuestionnaireResponses: Navigate to a patient's QuestionnaireResponses by selecting a patient and clicking on the "Questionnaire Responses" tab.
-
Select a QuestionnaireResponse: Click on a QuestionnaireResponse in the list to expand its details.
-
Convert to PFE Assessments: For completed QuestionnaireResponses that don't already have PFE Observations, click the "Convert to PFE Assessments" button at the bottom of the expanded details.
-
Monitor Conversion Progress: The conversion process runs in the background. You can monitor its progress in the task status panel at the top of the page.
-
View Derived PFE Assessments: Once the conversion is complete, a "View Derived PFE Assessments" button will appear, and the QuestionnaireResponse will be marked with a "PFE" badge. Click the button to view the generated PFE Observations.
-
View PFE Assessments: After clicking "View Derived PFE Assessments", you'll be taken to the Observations page where you can see the newly created PFE Observations.
This application uses RSpec for testing. You can find tests in the spec/ folder, organized by models, controllers, and features.
-
Running the Test Suite
bundle exec rspec -
Factories
We use
FactoryBotgem to mock objects for testing. Check thespec/factoriesdirectory for defined factories.
-
Start the app:
./bin/dev
-
Run RSpec tests:
bundle exec rspec -
Check for code linting (Rubocop):
bundle exec rubocop -
Run database migrations:
rails db:migrate
-
Scrape FHIR sample data:
bundle exec rake sample_data:scrapeThis rake task scrapes and downloads Betsy Smith-Johnson sample FHIR resources from the PACIO sample data depo FSH. It organizes the JSON files by scene and resource type in the
sample_use_casesfolder. The task is automatically run when loading sample data through the application, with a 5-hour cache to prevent excessive scraping operations. -
Push FHIR resources to a server:
bundle exec rake fhir:push[release_tag,fhir_server_url]This rake task pushes FHIR resources to a FHIR server. It takes two arguments:
release_tag: The sample data release to push, from https://paciowg.github.io/sample-data-fsh/fhir_server_url: The FHIR server to push to
Example:
bundle exec rake fhir:push[pacio-sample-data,http://hapi.fhir.org/baseR4] -
Transform QuestionnaireResponses to Observations:
bundle exec rake "fhir:fetch_and_transform_qr[server_url,patient_id]"
Fetches all QuestionnaireResponses for a given patient from the specified FHIR server, converts them into PFE Observation Bundles, and stores them in
tmp/fhir_bundles/. Semantic matching is used to infer domain categories. -
Submit transformed bundles to a FHIR server:
bundle exec rake "fhir:submit_bundles[server_url]"
Submits all bundles in
tmp/fhir_bundles/as FHIR transaction bundles to the specified server. Logs outcomes for each submission. -
Extract conformance requirements from a capability statement:
bundle exec rake "capability_statement:extract_requirements[path/to/capability_statement.json]"
Extracts conformance requirements from a FHIR capability statement JSON file and writes them to an Excel file in the
./requirementsdirectory. The Excel file is named based on the capability statement title (in snake case) and includes columns for URL, requirement, conformance level (SHALL, SHOULD, MAY), and actor (server/client).Note: The generated requirements file should be reviewed and corrected by a human to ensure accuracy, as the automated extraction may not capture all nuances of the capability statement.
-
Generate PFE domain mapping:
bundle exec rake pfe:generate_domain_mappingDownloads the PFE domain CodeSystem and saves them locally in
config/pfe_domain_mapping.ymlfor use in domain code detection.
Please read the Contributing to PseudoEHR guide and our Style Guidelines.
This project is licensed under the Apache License. See the LICENSE file for details.




