In this section you will implement email alerts to a radiologist when an exam in the worklist is over 7 days old.
Prerequisites¶
Email will be sent using the Rails mailer ActionMailer.
Email¶
Start by creating a mailer app/mailers/alert.rb
:
class Alert < ActionMailer::Base
default from: '[email protected]'
def too_old(count,entity_manager)
@host = Java::HarbingerSdkData::ConfigurationVariable.firstWith({".configurationKey" => "host"},entity_manager).configurationValue
@count = count
q = Java::HarbingerSdkData::Employee.createQuery(entity_manager)
q.where([q.equal(".employeeClinicalRoleMappings.clinicalRole.clinicalRole","radiologist")])
rad_emails = q.list.to_a.inject([]) do |list,employee|
email = employee.demographicHash["email"]
list << email unless email.blank?
list
end
mail(bcc: rad_emails, subject: 'exam(s) on the worklist too')
end
end
Best Practice - This example has a hardcoded
from
address in theAlert
model for convenience in the tutorial. This app would not be approved for production without a configurablefrom
address, due to the requirements of interacting with various email systems. Similarly, the entire concept of sending email automatically would require an enable/disable feature, particularly since the potential audience and frequency of such emails could be hundreds of people multiple times an hour.
The too_old
method takes two arguments: an entity manager and the count of exams that are too old. Inside the method, the SDK is used to pull get a list of all employee records with an associated clinical role of radiologist
. That list is filtered to keep all records with an email address. Finally, the mail command is run to send the email. By convention, an ActionMailer
method creates the email body by rendering a view. Create that view in app/views/alert/too_old.text.erb
:
There are <%= @count %> exams that are older than 7 days.
Please take a look at the worklist <%= url_for(host: @host, controller: :worklist, action: :index) %>.
The view has access to all instance variables set in the mailer method. Links in emails need to be handled differently than those in a web page: you must specify a host in the options passed to url_for
. There is not a reliable way to get the correct host from rails
, but the platform provides this through the ConfigurationVariable
model, using the record with a configuration_key
of host
. You can create an HTML format email and use helper functions like link_to
following the same principle (also requiring the same host
information).
You can test the email and see the headers and body printed to the log by running Alert.too_old(5,nil)
in the Rails console.
Background task¶
You need to build a background task with a query to get the count of exams, determines if an email should be sent, and evaluate regularly. Create a new controller to handler this, app/controllers/alerts_controller.rb
:
class AlertsController < ApplicationController
before_filter :get_entity_manager
def too_old
query = Java::HarbingerSdkData::RadExam.createQuery(@entity_manager)
query.select(query.count(".id"))
query.where([ query.equal(".currentStatus.universalEventType.eventType","complete"),
query.greaterThan(".radExamTime.endExam",7.days.ago.to_time)])
count = query.first
if count.size > 0
Alert.too_old(count,@entity_manager).deliver_now
end
render status: 200, text: "sucessfully sent email alerts #{count}"
end
end
Bridge is not set up to handle the use of deliver_later
, you must use deliver_now
when sending email.
Add a route for the controller, edit config/routes.rb
:
get 'alerts/too_old' => "alerts/too_old"
You can run that method/action from a browser or as an API call, but that will not run periodically in the background as desired.
The current solution for background tasks is to add a curl request to the application server crontab on the desired schedule. This is a manual deployment task, so please document how it needs to work.
Background jobs need to be secured to not run by mistake or without authorization, so create a new filter in the application controller:
def cron_authenticate()
if params[:api_key] != "9o8ajewfj9283jflaksueau4938jff"
render status: 401, text: "Incorrect cron api key"
return false
else
return true
end
end
Best Practice - As is the case with the
from
address in our mailer, it would be required to have a configuration page to edit the API key (rather than hardcoding it like this example code) for this application to be approved and deployed in production.
Finally, add the before_filter
call to app/controllers/alerts_controller.rb
:
class AlertsController < ApplicationController
before_filter :cron_authenticate
before_filter :get_entity_manager
#...
Invoking the mailer now requires the API key. Here is an example curl request that would be put into crontab to execute the too_long
alert:
curl 'http://server.example.com/railsdevelopertutorial/alerts/too_old?api_key=9o8ajewfj9283jflaksueau4938jff'