ion_orders_engine_mockingjay 1.0.1.SNAPSHOT
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 +7 -0
- data/README.md +0 -0
- data/Rakefile +4 -0
- data/app/assets/images/rails.png +0 -0
- data/app/assets/javascripts/application.js +16 -0
- data/app/assets/javascripts/bootstrap_additions.js.coffee +4 -0
- data/app/assets/javascripts/interchange/patients.js.coffee +3 -0
- data/app/assets/javascripts/interchange/physicians.js.coffee +3 -0
- data/app/assets/javascripts/mock/allergies.js.coffee +3 -0
- data/app/assets/javascripts/mock/appointments.js.coffee +3 -0
- data/app/assets/javascripts/mock/assignments.js.coffee +17 -0
- data/app/assets/javascripts/mock/chart_reviews.js.coffee +3 -0
- data/app/assets/javascripts/mock/comments.js.coffee +3 -0
- data/app/assets/javascripts/mock/conditions.js.coffee +3 -0
- data/app/assets/javascripts/mock/diagnoses.js.coffee +3 -0
- data/app/assets/javascripts/mock/documents.js.coffee +3 -0
- data/app/assets/javascripts/mock/employments.js.coffee +3 -0
- data/app/assets/javascripts/mock/encounters.js.coffee +3 -0
- data/app/assets/javascripts/mock/family_contacts.js.coffee +3 -0
- data/app/assets/javascripts/mock/family_histories.js.coffee +3 -0
- data/app/assets/javascripts/mock/guarantors.js.coffee +3 -0
- data/app/assets/javascripts/mock/insurance_plans.js.coffee +3 -0
- data/app/assets/javascripts/mock/lab_concepts.js.coffee +4 -0
- data/app/assets/javascripts/mock/lab_results.js.coffee +3 -0
- data/app/assets/javascripts/mock/locations.js.coffee +3 -0
- data/app/assets/javascripts/mock/medical_record_numbers.js.coffee +3 -0
- data/app/assets/javascripts/mock/metadata_keywords.js.coffee +3 -0
- data/app/assets/javascripts/mock/pharmacies.js.coffee +3 -0
- data/app/assets/javascripts/mock/phone_numbers.js.coffee +3 -0
- data/app/assets/javascripts/mock/physicians.js.coffee +3 -0
- data/app/assets/javascripts/mock/procedure_histories.js.coffee +3 -0
- data/app/assets/javascripts/mock/providers.js.coffee +14 -0
- data/app/assets/javascripts/mock/questions.js.coffee +3 -0
- data/app/assets/javascripts/mock/reference_range.js.coffee +3 -0
- data/app/assets/javascripts/mock/sections.js.coffee +3 -0
- data/app/assets/javascripts/mock/social_histories.js.coffee +3 -0
- data/app/assets/javascripts/mock/state_health_identifiers.js.coffee +3 -0
- data/app/assets/javascripts/mock/statistics.js.coffee +3 -0
- data/app/assets/javascripts/mock/test_assertions.js.coffee +3 -0
- data/app/assets/javascripts/mock/visit.js.coffee +3 -0
- data/app/assets/javascripts/mock/vitals_measurement.js.coffee +3 -0
- data/app/assets/javascripts/reference/data_elements.js.coffee +3 -0
- data/app/assets/javascripts/reference/data_lists.js.coffee +3 -0
- data/app/assets/javascripts/reference/data_sets.js.coffee +3 -0
- data/app/assets/stylesheets/application.css.scss +13 -0
- data/app/assets/stylesheets/bootstrap_and_overrides.css.scss +79 -0
- data/app/assets/stylesheets/forms.css.scss +67 -0
- data/app/assets/stylesheets/interchange/patients.css.scss +3 -0
- data/app/assets/stylesheets/interchange/physicians.css.scss +3 -0
- data/app/assets/stylesheets/mock/allergies.css.scss +3 -0
- data/app/assets/stylesheets/mock/appointments.css.scss +3 -0
- data/app/assets/stylesheets/mock/chart_reviews.css.scss +3 -0
- data/app/assets/stylesheets/mock/comments.css.scss +3 -0
- data/app/assets/stylesheets/mock/conditions.css.scss +3 -0
- data/app/assets/stylesheets/mock/diagnoses.css.scss +3 -0
- data/app/assets/stylesheets/mock/documents.css.scss +3 -0
- data/app/assets/stylesheets/mock/employments.css.scss +3 -0
- data/app/assets/stylesheets/mock/encounters.css.scss +3 -0
- data/app/assets/stylesheets/mock/family_contacts.css.scss +3 -0
- data/app/assets/stylesheets/mock/family_histories.css.scss +3 -0
- data/app/assets/stylesheets/mock/guarantors.css.scss +3 -0
- data/app/assets/stylesheets/mock/insurance_plans.css.scss +3 -0
- data/app/assets/stylesheets/mock/lab_concepts.css.scss +3 -0
- data/app/assets/stylesheets/mock/lab_results.css.scss +3 -0
- data/app/assets/stylesheets/mock/locations.css.scss +3 -0
- data/app/assets/stylesheets/mock/medical_record_numbers.css.scss +3 -0
- data/app/assets/stylesheets/mock/metadata_keywords.css.scss +3 -0
- data/app/assets/stylesheets/mock/pharmacies.css.scss +3 -0
- data/app/assets/stylesheets/mock/phone_numbers.css.scss +3 -0
- data/app/assets/stylesheets/mock/physicians.css.scss +3 -0
- data/app/assets/stylesheets/mock/procedure_histories.css.scss +3 -0
- data/app/assets/stylesheets/mock/providers.css.scss +3 -0
- data/app/assets/stylesheets/mock/questions.css.scss +3 -0
- data/app/assets/stylesheets/mock/reference_range.css.scss +3 -0
- data/app/assets/stylesheets/mock/sections.css.scss +3 -0
- data/app/assets/stylesheets/mock/social_histories.css.scss +3 -0
- data/app/assets/stylesheets/mock/state_health_identifiers.css.scss +3 -0
- data/app/assets/stylesheets/mock/statistics.css.scss +3 -0
- data/app/assets/stylesheets/mock/test_assertions.css.scss +3 -0
- data/app/assets/stylesheets/mock/visit.css.scss +3 -0
- data/app/assets/stylesheets/mock/vitals_measurement.css.scss +3 -0
- data/app/assets/stylesheets/reference/data_elements.css.scss +3 -0
- data/app/assets/stylesheets/reference/data_lists.css.scss +3 -0
- data/app/assets/stylesheets/reference/data_sets.css.scss +3 -0
- data/app/assets/stylesheets/scaffolds.css.scss +66 -0
- data/app/controllers/api/base_controller.rb +78 -0
- data/app/controllers/api/ion_orders_engine/order_by_id/order_by_id_controller.rb +3220 -0
- data/app/controllers/api/ion_orders_engine/order_profile/inpatient_order_profile_controller.rb +3156 -0
- data/app/controllers/application_controller.rb +25 -0
- data/app/controllers/crud/base_controller.rb +90 -0
- data/app/controllers/interchange/base_controller.rb +63 -0
- data/app/controllers/interchange/data_sets_controller.rb +40 -0
- data/app/controllers/interchange/exports_controller.rb +120 -0
- data/app/controllers/interchange/imports_controller.rb +141 -0
- data/app/controllers/reference/base_controller.rb +7 -0
- data/app/controllers/reference/data_lists_controller.rb +177 -0
- data/app/controllers/reference/data_options_controller.rb +147 -0
- data/app/controllers/reference/data_sets_controller.rb +160 -0
- data/app/helpers/application_helper.rb +389 -0
- data/app/helpers/error_messages_helper.rb +23 -0
- data/app/helpers/interchange/exports_helper.rb +9 -0
- data/app/helpers/interchange/imports_helper.rb +31 -0
- data/app/helpers/layout_helper.rb +40 -0
- data/app/helpers/reference/data_elements_helper.rb +2 -0
- data/app/helpers/reference/data_lists_helper.rb +2 -0
- data/app/helpers/reference/data_sets_helper.rb +2 -0
- data/app/views/interchange/common/_database_info.json.jbuilder +6 -0
- data/app/views/interchange/common/_metadata_keywords.json.jbuilder +13 -0
- data/app/views/interchange/common/_test_assertions.json.jbuilder +17 -0
- data/app/views/interchange/data_sets/_data_list.json.jbuilder +14 -0
- data/app/views/interchange/data_sets/_data_option.json.jbuilder +12 -0
- data/app/views/interchange/data_sets/_data_set.json.jbuilder +17 -0
- data/app/views/interchange/data_sets/_nested_data_list.json.jbuilder +12 -0
- data/app/views/interchange/data_sets/show.json.jbuilder +10 -0
- data/app/views/interchange/document_templates/_document_template.json.jbuilder +23 -0
- data/app/views/interchange/document_templates/_section.json.jbuilder +11 -0
- data/app/views/interchange/document_templates/show.json.jbuilder +10 -0
- data/app/views/interchange/exports/_export_summary.html.erb +49 -0
- data/app/views/interchange/exports/show.html.erb +35 -0
- data/app/views/interchange/imports/_import_summary.html.erb +72 -0
- data/app/views/interchange/imports/show.html.erb +37 -0
- data/app/views/layouts/_flashbar.html.erb +6 -0
- data/app/views/layouts/_navbar.html.erb +38 -0
- data/app/views/layouts/_protected_warning.html.erb +7 -0
- data/app/views/layouts/_root_model_layout.erb +33 -0
- data/app/views/layouts/application.html.erb +39 -0
- data/app/views/layouts/reference/data_sets.html.erb +5 -0
- data/app/views/reference/data_lists/_data_options.html.erb +31 -0
- data/app/views/reference/data_lists/_form.html.erb +23 -0
- data/app/views/reference/data_lists/edit.html.erb +6 -0
- data/app/views/reference/data_lists/index.html.erb +31 -0
- data/app/views/reference/data_lists/new.html.erb +6 -0
- data/app/views/reference/data_lists/show.html.erb +55 -0
- data/app/views/reference/data_options/_form.html.erb +23 -0
- data/app/views/reference/data_options/edit.html.erb +5 -0
- data/app/views/reference/data_options/index.html.erb +38 -0
- data/app/views/reference/data_options/new.html.erb +5 -0
- data/app/views/reference/data_options/show.html.erb +33 -0
- data/app/views/reference/data_sets/_form.html.erb +25 -0
- data/app/views/reference/data_sets/edit.html.erb +5 -0
- data/app/views/reference/data_sets/index.html.erb +40 -0
- data/app/views/reference/data_sets/new.html.erb +5 -0
- data/app/views/reference/data_sets/show.html.erb +38 -0
- data/config/application.rb +100 -0
- data/config/boot.rb +6 -0
- data/config/database.yml +25 -0
- data/config/environment.rb +5 -0
- data/config/environments/development.rb +42 -0
- data/config/environments/production.rb +64 -0
- data/config/environments/test.rb +35 -0
- data/config/initializers/backtrace_silencers.rb +7 -0
- data/config/initializers/extensions/active_record.rb +13 -0
- data/config/initializers/extensions/hash.rb +11 -0
- data/config/initializers/extensions/string.rb +15 -0
- data/config/initializers/inflections.rb +15 -0
- data/config/initializers/mime_types.rb +5 -0
- data/config/initializers/reference.rb +77 -0
- data/config/initializers/secret_token.rb +7 -0
- data/config/initializers/session_store.rb +8 -0
- data/config/initializers/simple_form.rb +142 -0
- data/config/initializers/simple_form_bootstrap.rb +45 -0
- data/config/initializers/wrap_parameters.rb +10 -0
- data/config/locales/en.yml +207 -0
- data/config/locales/simple_form.en.yml +26 -0
- data/config/mongo.yml +18 -0
- data/config/routes.rb +4 -0
- data/db/schema.rb +16 -0
- data/db/seeds.rb +66 -0
- data/lib/ion_orders_engine_mockingjay/engine.rb +13 -0
- data/lib/ion_orders_engine_mockingjay/version.rb +3 -0
- data/lib/ion_orders_engine_mockingjay.rb +4 -0
- data/lib/tasks/ion_orders_engine_mockingjay_tasks.rake +4 -0
- metadata +215 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
class ApplicationController < ActionController::Base
|
2
|
+
# Mixins
|
3
|
+
include ::Mixins::Logging
|
4
|
+
|
5
|
+
protect_from_forgery
|
6
|
+
|
7
|
+
helper :layout
|
8
|
+
|
9
|
+
before_filter :reload_reference_data
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
# TODO: Fix this hack by using a persistent key-value store in development.
|
14
|
+
# This will reload our reference data if is has been unloaded.
|
15
|
+
def reload_reference_data
|
16
|
+
log "ApplicationController reload_reference_data(): Reference.get_instances_hash is: #{Reference.get_instances_hash}"
|
17
|
+
if Reference.empty_cache?
|
18
|
+
log "ApplicationController reload_reference_data(): Determined that we need to reload reference data. Doing so now."
|
19
|
+
Reference::DataTypes.reload if ActiveRecord::Base.connection.table_exists? 'reference_data_lists'
|
20
|
+
else
|
21
|
+
log "ApplicationController reload_reference_data(): No need to reload reference data."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
class Crud::BaseController < ApplicationController
|
2
|
+
|
3
|
+
protected
|
4
|
+
|
5
|
+
# Internal: By default, paths we construct will not be prefixed with a module symbol.
|
6
|
+
# However, in cases where controllers use a module namespace not shared by the models
|
7
|
+
# they operate on, subclasses of this class should include the symbol paths should
|
8
|
+
# be prefixed with. For example:
|
9
|
+
#
|
10
|
+
# :mock
|
11
|
+
def module_symbol_for_paths
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# Makes all breadcrumb calls from the root resource to the model provided.
|
16
|
+
# If an optional last breadcrumb symbol is provided, we add a breadcrumb for
|
17
|
+
# that too. The last breadcrumb always has a link href value of '#'.
|
18
|
+
# We leverage the breadcrumbs_on_rails gem to handle the mechanics of building
|
19
|
+
# the display tree from our calls to its API.
|
20
|
+
#
|
21
|
+
# We only ever pull in two resources max, to form the URL, since we never go deeper
|
22
|
+
# than one level of resource nesting.
|
23
|
+
#
|
24
|
+
# If the current element in the ancestors chain we retrieve is not a symbol, and it
|
25
|
+
# responds to 'short_title', we'll append that to the breadcrumb name, after a colon.
|
26
|
+
def configure_breadcrumbs(model, last_crumb_symbol=nil)
|
27
|
+
if model.is_a?(Symbol)
|
28
|
+
ancestors = [model]
|
29
|
+
else
|
30
|
+
ancestors = model.resource_ancestors
|
31
|
+
end
|
32
|
+
|
33
|
+
ancestors.push(last_crumb_symbol) unless last_crumb_symbol.nil?
|
34
|
+
total_crumbs = ancestors.length
|
35
|
+
log "ancestors has #{ancestors.length} elements. They are: #{ancestors}"
|
36
|
+
|
37
|
+
ancestors.each_with_index do | resource, index |
|
38
|
+
# Is this breadcrumb name going to be based on a symbol?
|
39
|
+
if resource.is_a?(Symbol)
|
40
|
+
crumb_name = resource.to_s.humanize.titleize
|
41
|
+
else
|
42
|
+
crumb_name = resource.class.model_name.tableize.humanize.singularize.titleize.split('/').last
|
43
|
+
crumb_name.concat(": #{resource.short_title}") if resource.short_title
|
44
|
+
end
|
45
|
+
|
46
|
+
# Are we dealing with a nested resource?
|
47
|
+
if index > 0
|
48
|
+
parent_resource = [ ancestors[index-1] ]
|
49
|
+
else
|
50
|
+
parent_resource = []
|
51
|
+
end
|
52
|
+
|
53
|
+
# Determine what the path should start off with. Namely, allow for the case
|
54
|
+
# that a module namespace might be needed; provided by a subclass'
|
55
|
+
# implementation of module_symbol_for_paths:
|
56
|
+
base_path = if module_symbol_for_paths
|
57
|
+
[module_symbol_for_paths]
|
58
|
+
else
|
59
|
+
[]
|
60
|
+
end
|
61
|
+
|
62
|
+
crumb_path_array = base_path.concat(parent_resource).push(ancestors[index])
|
63
|
+
|
64
|
+
# Are we processing the last breadcrumb in the sequence?
|
65
|
+
if index == (total_crumbs - 1)
|
66
|
+
# YES: So cue breadcrumbs_on_rails to use a no-op URL and a diffused CSS style.
|
67
|
+
url = '#'
|
68
|
+
options = {class: 'active'}
|
69
|
+
else
|
70
|
+
# NO: Do allow this breadcrumb to be a real link to its resource.
|
71
|
+
current_resource = crumb_path_array.last
|
72
|
+
|
73
|
+
# Is the current model a singular child resource?
|
74
|
+
if current_resource.is_singular_child_resource?
|
75
|
+
# YES. So we need to swap it out in the crumb path array with
|
76
|
+
# a singular symbol of itself instead, so that when passed to url_for(),
|
77
|
+
# a correct URL path will be constructed.
|
78
|
+
crumb_path_array[-1] = crumb_path_array.last.class.to_s.tableize.singularize.to_sym
|
79
|
+
end
|
80
|
+
|
81
|
+
url = url_for(crumb_path_array)
|
82
|
+
options = {}
|
83
|
+
end
|
84
|
+
|
85
|
+
add_breadcrumb crumb_name, url, options # breadcrumbs_on_rails call
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
class Interchange::BaseController < ApplicationController
|
2
|
+
|
3
|
+
# This constructor sets up a writer class, which we'll use if we do any export for automation or export for
|
4
|
+
# later import purposes. The writer handles the details of writing a model's contents to disk.
|
5
|
+
def initialize
|
6
|
+
super
|
7
|
+
@writer = Interchange::Writer.new
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
# NOTE: This method is meant to be called by a subclass, that sets up the
|
12
|
+
# @model instance variable for us (along with other instance variables
|
13
|
+
# that the template we render would be expecting).
|
14
|
+
def show
|
15
|
+
pretty_json = render_show_template_to_string(@model, params) # Calls the two-parameter variant our subclasses should implement
|
16
|
+
decorated_json = @writer.decorate_output(@model, pretty_json, params)
|
17
|
+
render json: decorated_json
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
# Takes a string of raw JSON and renders it pretty.
|
24
|
+
# If no JSON string is provided, we'll do a render to string that runs
|
25
|
+
# under the auspices of the current controller action calling us
|
26
|
+
# (or the template for the specified action).
|
27
|
+
def render_to_string_pretty_json(json_string=nil, options={})
|
28
|
+
unless json_string
|
29
|
+
# Use the calling action's view template to produce JSON:
|
30
|
+
if options[:template]
|
31
|
+
json_string = render_to_string(formats: :json, action: options[:template])
|
32
|
+
else
|
33
|
+
json_string = render_to_string(formats: :json)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Reverse any newline escaping that happens right at the jbuilder stage:
|
38
|
+
json_string.gsub!('\\\n', '\n')
|
39
|
+
|
40
|
+
# Parse and return the pretty JSON string:
|
41
|
+
json_object = JSON.parse(json_string)
|
42
|
+
pretty_json = JSON.pretty_generate(json_object)
|
43
|
+
render_to_string json: pretty_json
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# NOTE: This is not a standalone method. It is meant to be called by our subclasses,
|
48
|
+
# after they have setup instance variables that will be used in processing their
|
49
|
+
# 'show' action JSON template.
|
50
|
+
#
|
51
|
+
# We return the result of generating a pretty JSON representation from the 'show' template,
|
52
|
+
# as defined by the subclass controller that invokes us.
|
53
|
+
def render_show_template_to_string(options={})
|
54
|
+
@suppress_database_timestamps = true
|
55
|
+
|
56
|
+
# Since we use ids now to stitch together pointers within an export file, default this
|
57
|
+
# to false unless requested otherwise:
|
58
|
+
@suppress_database_ids = options[:suppress_database_ids]
|
59
|
+
render_to_string_pretty_json(nil, template: 'show')
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
end # class
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Interchange::DataSetsController < Interchange::BaseController
|
2
|
+
|
3
|
+
alias :super_render_show_template_to_string :render_show_template_to_string
|
4
|
+
alias :super_show :show
|
5
|
+
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
super
|
9
|
+
@model_class = DataSet
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
# ---------- Exporting ----------
|
14
|
+
|
15
|
+
# Shows a data set's JSON representation in the browser.
|
16
|
+
def show
|
17
|
+
# Find the data set and set the @data_set variable, which the jbuilder template will look for:
|
18
|
+
@data_set = DataSet.find(params[:id])
|
19
|
+
|
20
|
+
# Alias the @data_set variable to @model, which our superclass' implementation needs:
|
21
|
+
@model = @data_set
|
22
|
+
|
23
|
+
# Invoke the superclass implementation to do the rendering work:
|
24
|
+
super_show
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# Returns a DataSet's JSON representation as a string.
|
29
|
+
#
|
30
|
+
# We setup the instance variables that the rendered template would need for the
|
31
|
+
# given data set. We then return the result of generating a pretty JSON representation
|
32
|
+
# of the data set, by calling our superclass variant of this method.
|
33
|
+
def render_show_template_to_string(data_set, options={})
|
34
|
+
@data_set = data_set
|
35
|
+
super_render_show_template_to_string(options)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
end # class
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# Controller for export related functionality, as a RESTful resource. We handle both
|
2
|
+
# regular exports and exports bound for UIAutomation .js data files.
|
3
|
+
class Interchange::ExportsController < ApplicationController
|
4
|
+
|
5
|
+
layout 'application'
|
6
|
+
|
7
|
+
# This constructor sets up Writer class that we offload the low level export work to.
|
8
|
+
def initialize
|
9
|
+
super
|
10
|
+
@writer = Interchange::Writer.new
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
# Shows the page of export options, as well as the results of the last export operation,
|
15
|
+
# if the server hasn't been bounced since that was last performed.
|
16
|
+
def show
|
17
|
+
log 'ExportsController: show'
|
18
|
+
marshal_options_from_session
|
19
|
+
options = {class: 'active'}
|
20
|
+
add_breadcrumb 'Export', '#', options # breadcrumbs_on_rails call
|
21
|
+
|
22
|
+
# Retrieve results of the last export, so we can display that in our view:
|
23
|
+
@last_export_summary = Interchange::Writer.instance_variable_get(:@last_export_summary)
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
# This responds to the request to do the export. We invoke a helper method to handle the
|
28
|
+
# export of a given model class, one class at a time. Possible param values that can be provided:
|
29
|
+
# * export_patients - Whether to export patients. Pass 1 for true.
|
30
|
+
# * export_physicians - Whether to export physicians. Pass 1 for true.
|
31
|
+
# * model_class_name - Indicates a single class we want exported. Use along with model_id to export a single object.
|
32
|
+
# * model_id - The id value of the single object we want to export. Use along with model_class_name to export a single object.
|
33
|
+
# * ids - A specific set of ID values to export (as opposed to all for the specified model class).
|
34
|
+
# * restrict_by_keywords - Whether to restrict models exported to those with one of the keywords provided by keywords_csv.
|
35
|
+
# * keywords_csv - A string of keywords, comma separated. These are keywords a model
|
36
|
+
# must have one of, in order to be included in the export.
|
37
|
+
# We determine what models to export from the params provided.
|
38
|
+
# Once complete, we redirect to the show action, with a flash message built from the
|
39
|
+
# Interchange::Writer class' tally of results.
|
40
|
+
def create
|
41
|
+
log 'In create method. Initiating an export operation now.'
|
42
|
+
log "params: #{params}"
|
43
|
+
|
44
|
+
marshal_options_to_session
|
45
|
+
|
46
|
+
# Determine what models are to be included:
|
47
|
+
model_classes = []
|
48
|
+
|
49
|
+
model_classes << Patient if params[:export_patients]
|
50
|
+
model_classes << Physician if params[:export_physicians]
|
51
|
+
model_classes << DocumentTemplate if params[:export_document_templates]
|
52
|
+
model_classes << DataSet if params[:export_data_sets]
|
53
|
+
|
54
|
+
# Did we have a specific model class given for export?
|
55
|
+
if params[:model_class_name]
|
56
|
+
# YES: Export just that class and just the ID provided:
|
57
|
+
model_classes << params[:model_class_name].constantize
|
58
|
+
ids = [params[:model_id]] if params[:model_id]
|
59
|
+
end
|
60
|
+
|
61
|
+
# If not already specified by model_id, look for a subset of IDs to
|
62
|
+
# restrict the export to:
|
63
|
+
ids = params[:ids] unless ids
|
64
|
+
|
65
|
+
# Determine if there are keywords requested for us to filter by:
|
66
|
+
keywords =
|
67
|
+
if params[:restrict_by_keywords] && !params[:keywords_csv].blank?
|
68
|
+
params[:keywords_csv].split(',')
|
69
|
+
else
|
70
|
+
nil
|
71
|
+
end
|
72
|
+
|
73
|
+
keywords.each do | keyword |
|
74
|
+
keyword.strip!
|
75
|
+
end if keywords
|
76
|
+
|
77
|
+
# Start the export operation block:
|
78
|
+
@writer.mark_export_operation do
|
79
|
+
# Kick off the underlying export operation on the model(s) requested:
|
80
|
+
model_classes.each do |model_class|
|
81
|
+
@writer.export model_class, {keywords: keywords, ids: ids}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
redirect_to interchange_export_path, @writer.operation_results[:flash_hash]
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
protected
|
90
|
+
|
91
|
+
# Take the various options specified in the export dialog, which came along
|
92
|
+
# in the params hash, and store them in a @selections variable, which itself,
|
93
|
+
# gets stored in the session object. This allows for later retrieval of these
|
94
|
+
# options on a subsequent request-response cycle, so that these preferences
|
95
|
+
# (options) appear to be remembered.
|
96
|
+
def marshal_options_to_session
|
97
|
+
@selections = @selections || {}
|
98
|
+
@selections[:export_patients] = params[:export_patients]
|
99
|
+
@selections[:export_physicians] = params[:export_physicians]
|
100
|
+
@selections[:export_document_templates] = params[:export_document_templates]
|
101
|
+
@selections[:export_data_sets] = params[:export_data_sets]
|
102
|
+
@selections[:restrict_by_keywords] = params[:restrict_by_keywords]
|
103
|
+
@selections[:keywords_csv] = params[:keywords_csv]
|
104
|
+
|
105
|
+
session[self.class.to_s] ||= {}
|
106
|
+
session[self.class.to_s][:selections] = @selections
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# Retrieves the @selections hash from the session hash, which was originally
|
111
|
+
# stored in the method marshal_options_to_session. This allows us to have
|
112
|
+
# an instance variable setup for the view that will drive the UI to preselect
|
113
|
+
# the previously selected options.
|
114
|
+
def marshal_options_from_session
|
115
|
+
session[self.class.to_s] ||= {}
|
116
|
+
@selections = session[self.class.to_s][:selections] || {}
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
end # class
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# Controller for a import related functionality, as a RESTful resource.
|
2
|
+
class Interchange::ImportsController < ApplicationController
|
3
|
+
|
4
|
+
layout 'application'
|
5
|
+
|
6
|
+
# This constructor sets up Reader class that we offload the low level import work to.
|
7
|
+
def initialize
|
8
|
+
super
|
9
|
+
@reader = Interchange::Reader.new
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
# Shows the page of import options, as well as the results of the last import operation,
|
14
|
+
# if the server hasn't been bounced since that was last performed.
|
15
|
+
def show
|
16
|
+
log 'ImportController: show'
|
17
|
+
marshal_options_from_session
|
18
|
+
options = {class: 'active'}
|
19
|
+
add_breadcrumb 'Import', '#', options # breadcrumbs_on_rails call
|
20
|
+
|
21
|
+
# Retrieve results of the last import, so we can display that in our view:
|
22
|
+
@last_import_summary = Interchange::Reader.instance_variable_get(:@last_import_summary)
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# This responds to the request to do the import. We invoke a helper method to handle the
|
27
|
+
# import of a given model class, one at a time. Possible param values that can be provided:
|
28
|
+
# * import_patients - Whether to import patients. Pass 1 for true.
|
29
|
+
# * import_physicians - Whether to import physicians. Pass 1 for true.
|
30
|
+
# * destroy_existing - Whether to destroy existing data before starting the import. Pass 1 for true.
|
31
|
+
# * cleanup - Whether to delete source files that are successfully imported. Pass 1 for true.
|
32
|
+
#
|
33
|
+
# We determine what models to import from the params provided, as well as whether to delete
|
34
|
+
# existing data prior to import and source import data after successful import.
|
35
|
+
# Once complete, we redirect to the show action, with a flash message built from the
|
36
|
+
# Interchange::Reader class' tally of results.
|
37
|
+
def create
|
38
|
+
log 'In create method. Initiating an import operation now.'
|
39
|
+
log "params: #{params}"
|
40
|
+
|
41
|
+
# Determine what models are to be included:
|
42
|
+
model_classes = []
|
43
|
+
model_classes << Patient if params[:import_patients]
|
44
|
+
model_classes << Physician if params[:import_physicians]
|
45
|
+
model_classes << DocumentTemplate if params[:import_document_templates]
|
46
|
+
model_classes << DataSet if params[:import_data_sets]
|
47
|
+
|
48
|
+
# Determine what options have been requested:
|
49
|
+
destroy_existing = params[:destroy_existing]
|
50
|
+
cleanup = params[:cleanup]
|
51
|
+
|
52
|
+
duplicate_strategy =
|
53
|
+
case params[:duplicates]
|
54
|
+
when 'Allow' then
|
55
|
+
Enums::DuplicateStrategy::ALLOW
|
56
|
+
when 'Replace' then
|
57
|
+
Enums::DuplicateStrategy::REPLACE
|
58
|
+
when 'Skip' then
|
59
|
+
Enums::DuplicateStrategy::SKIP
|
60
|
+
else
|
61
|
+
Enums::DuplicateStrategy::SKIP
|
62
|
+
end
|
63
|
+
|
64
|
+
marshal_options_to_session
|
65
|
+
|
66
|
+
@reader.mark_import_operation do
|
67
|
+
# Kick off the underlying import operation on the model(s) requested:
|
68
|
+
model_classes.each do |model_class|
|
69
|
+
import model_class, destroy_existing, cleanup, duplicate_strategy
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
redirect_to interchange_import_path, @reader.operation_results[:flash_hash]
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
protected
|
78
|
+
|
79
|
+
# Take the various options specified in the import dialog, which came along
|
80
|
+
# in the params hash, and store them in a @selections variable, which itself,
|
81
|
+
# gets stored in the session object. This allows for later retrieval of these
|
82
|
+
# options on a subsequent request-response cycle, so that these preferences
|
83
|
+
# (options) appear to be remembered.
|
84
|
+
def marshal_options_to_session
|
85
|
+
@selections = @selections || {}
|
86
|
+
@selections[:import_patients] = params[:import_patients]
|
87
|
+
@selections[:import_physicians] = params[:import_physicians]
|
88
|
+
@selections[:import_document_templates] = params[:import_document_templates]
|
89
|
+
@selections[:import_data_sets] = params[:import_data_sets]
|
90
|
+
@selections[:destroy_existing] = params[:destroy_existing]
|
91
|
+
@selections[:cleanup] = params[:cleanup]
|
92
|
+
@selections[:duplicates] = params[:duplicates]
|
93
|
+
|
94
|
+
session[self.class.to_s] ||= {}
|
95
|
+
session[self.class.to_s][:selections] = @selections
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
# Retrieves the @selections hash from the session hash, which was originally
|
100
|
+
# stored in the method marshal_options_to_session. This allows us to have
|
101
|
+
# an instance variable setup for the view that will drive the UI to preselect
|
102
|
+
# the previously selected options.
|
103
|
+
def marshal_options_from_session
|
104
|
+
session[self.class.to_s] ||= {}
|
105
|
+
@selections = session[self.class.to_s][:selections] || {}
|
106
|
+
|
107
|
+
# Provide a default of 'Replace' for the duplicate strategy, if not yet specified:
|
108
|
+
@selections[:duplicates] = 'Replace' unless @selections[:duplicates]
|
109
|
+
|
110
|
+
# Marshal duplicate strategy as boolean for each of the specific strategy keys:
|
111
|
+
@selections[:allow_duplicates] = (@selections[:duplicates] == 'Allow')
|
112
|
+
@selections[:skip_duplicates] = (@selections[:duplicates] == 'Skip')
|
113
|
+
@selections[:replace_duplicates] = (@selections[:duplicates] == 'Replace')
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
# ---------- Importing ----------
|
120
|
+
|
121
|
+
# Imports all source files for the given model class provided, using the options specified.
|
122
|
+
#
|
123
|
+
# @param model_class {Class} The model class we are to find source files to import, and import.
|
124
|
+
# @param destroy_existing {Boolean} Whether we are to destroy existing models belonging to model_class
|
125
|
+
# prior to the import operation.
|
126
|
+
# @param cleanup {Boolean} Whether to delete source import files for model instances that successfully imported.
|
127
|
+
# @param duplicate_strategy {Enums::DuplicateStrategy} A constant indicating how to handle duplicates.
|
128
|
+
def import(model_class, destroy_existing, cleanup, duplicate_strategy)
|
129
|
+
log "Importing files for model class: #{model_class}, with options: " \
|
130
|
+
"{destroy_existing: #{destroy_existing}, cleanup: #{cleanup}, duplicate_strategy: #{duplicate_strategy}}"
|
131
|
+
|
132
|
+
# Delete all records for this model, if requested:
|
133
|
+
if destroy_existing
|
134
|
+
log_info "Interchange::ImportsController: Asked to destroy all existing instances of #{model_class}."
|
135
|
+
model_class.all.each { |model_instance| model_instance.destroy }
|
136
|
+
end
|
137
|
+
|
138
|
+
@reader.import model_class, cleanup, duplicate_strategy
|
139
|
+
end
|
140
|
+
|
141
|
+
end # class
|
@@ -0,0 +1,177 @@
|
|
1
|
+
class Reference::DataListsController < Reference::BaseController
|
2
|
+
|
3
|
+
before_filter :retrieve_data_listable
|
4
|
+
|
5
|
+
|
6
|
+
# GET /reference/data_lists
|
7
|
+
# GET /reference/data_lists.json
|
8
|
+
#
|
9
|
+
# The index action should only ever be called on this polymorphic model in the
|
10
|
+
# context of a parent resource (our @data_listable).
|
11
|
+
def index
|
12
|
+
if @data_listable.instance_of?(DataOption)
|
13
|
+
redirect_to :show
|
14
|
+
end
|
15
|
+
|
16
|
+
@data_lists = @data_listable.data_lists
|
17
|
+
configure_breadcrumbs @data_listable, :data_lists
|
18
|
+
|
19
|
+
respond_to do |format|
|
20
|
+
format.html # index.html.erb
|
21
|
+
format.json { render json: @data_lists }
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# GET /reference/data_lists/1
|
27
|
+
# GET /reference/data_lists/1.json
|
28
|
+
def show
|
29
|
+
retrieve_data_list
|
30
|
+
|
31
|
+
respond_to do |format|
|
32
|
+
format.html # show.html.erb
|
33
|
+
format.json { render json: @data_list }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# GET /reference/data_lists/new
|
39
|
+
# GET /reference/data_lists/new.json
|
40
|
+
def new
|
41
|
+
@data_list = if @data_listable.instance_of?(DataOption)
|
42
|
+
DataList.new(DataList.default_options)
|
43
|
+
else
|
44
|
+
@data_listable.data_lists.new(DataList.default_options)
|
45
|
+
end
|
46
|
+
|
47
|
+
configure_breadcrumbs @data_listable, :data_list
|
48
|
+
|
49
|
+
respond_to do |format|
|
50
|
+
format.html # new.html.erb
|
51
|
+
format.json { render json: @data_list }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
# GET /reference/data_lists/1/edit
|
57
|
+
def edit
|
58
|
+
retrieve_data_list
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# POST /reference/data_lists
|
63
|
+
# POST /reference/data_lists.json
|
64
|
+
def create
|
65
|
+
@data_list = if @data_listable.instance_of?(DataOption)
|
66
|
+
@data_listable.nested_data_list = DataList.new(params[:data_list])
|
67
|
+
else
|
68
|
+
@data_listable.data_lists.new(params[:data_list])
|
69
|
+
end
|
70
|
+
|
71
|
+
respond_to do |format|
|
72
|
+
if @data_list.save
|
73
|
+
format.html do
|
74
|
+
success_path = if @data_listable.instance_of?(DataOption)
|
75
|
+
[:reference, @data_listable, :nested_data_list]
|
76
|
+
else
|
77
|
+
[:reference, @data_listable, @data_list]
|
78
|
+
end
|
79
|
+
|
80
|
+
redirect_to success_path, notice: 'Data List was successfully created.'
|
81
|
+
end
|
82
|
+
format.json { render json: @data_list, status: :created, location: @data_list }
|
83
|
+
else
|
84
|
+
format.html do
|
85
|
+
# Set breadcrumbs again, otherwise they'd be lost on render of 'new' template:
|
86
|
+
configure_breadcrumbs @data_listable, :data_list
|
87
|
+
render action: "new"
|
88
|
+
end
|
89
|
+
format.json { render json: @data_list.errors, status: :unprocessable_entity }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
# PUT /reference/data_lists/1
|
96
|
+
# PUT /reference/data_lists/1.json
|
97
|
+
def update
|
98
|
+
retrieve_data_list
|
99
|
+
|
100
|
+
respond_to do |format|
|
101
|
+
if @data_list.update_attributes(params[:data_list])
|
102
|
+
Reference::DataTypes.reload # Update all of our reference data, given the updated DataList
|
103
|
+
format.html { redirect_to [:reference, @data_listable, @data_list], notice: 'Data List was successfully updated.' }
|
104
|
+
format.json { head :no_content }
|
105
|
+
else
|
106
|
+
format.html { render action: "edit" }
|
107
|
+
format.json { render json: @data_list.errors, status: :unprocessable_entity }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# DELETE /reference/data_lists/1
|
114
|
+
# DELETE /reference/data_lists/1.json
|
115
|
+
def destroy
|
116
|
+
retrieve_data_list
|
117
|
+
root_resource = @data_list.root_resource
|
118
|
+
@data_list.destroy if @data_list
|
119
|
+
root_resource.export_update # Allow root resource to save update to disk
|
120
|
+
|
121
|
+
Reference::DataTypes.reload # Update all of our reference data, given the removed DataList
|
122
|
+
|
123
|
+
respond_to do |format|
|
124
|
+
format.html { redirect_to [:reference, @data_listable, :data_lists],
|
125
|
+
notice: 'Data List was successfully destroyed.' }
|
126
|
+
format.json { head :no_content }
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
# Find the data_listable resource we belong to.
|
135
|
+
# Credit: http://railscasts.com/episodes/154-polymorphic-association-revised
|
136
|
+
def retrieve_data_listable
|
137
|
+
resource, id = request.path.split('/')[2, 3] # Start at index 2 and not 1, because we use the reference namespace
|
138
|
+
log "Resource name retrieved: #{resource}"
|
139
|
+
@data_listable = resource.singularize.classify.constantize.find(id)
|
140
|
+
|
141
|
+
# Retrieve data_set through the resource ancestor chain, so layout template
|
142
|
+
# has something to work with re: special notifications:
|
143
|
+
@data_set = @data_listable.resource_ancestors.first
|
144
|
+
|
145
|
+
# alternative option per Railscasts on polymorhpic relationships:
|
146
|
+
# klass = [Allergy, Condition].detect { |c| params["#{c.name.underscore}_id"] }
|
147
|
+
# @data_listable = klass.find(params["#{klass.name.underscore}_id"])
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
# def retrieve_data_list
|
152
|
+
# @data_list = DataList.find(params[:id])
|
153
|
+
# configure_breadcrumbs @data_list
|
154
|
+
# end
|
155
|
+
|
156
|
+
|
157
|
+
def retrieve_data_list
|
158
|
+
retrieve_data_listable unless @data_listable
|
159
|
+
|
160
|
+
log "params: #{params}"
|
161
|
+
log "data_listable: #{@data_listable}"
|
162
|
+
|
163
|
+
@data_list = if params[:id] && !@data_listable.instance_of?(DataOption)
|
164
|
+
DataList.find(params[:id])
|
165
|
+
else
|
166
|
+
@data_listable.try(:nested_data_list)
|
167
|
+
end
|
168
|
+
|
169
|
+
|
170
|
+
if @data_list
|
171
|
+
configure_breadcrumbs @data_list
|
172
|
+
else
|
173
|
+
configure_breadcrumbs @data_listable, :data_list
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|