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.
Files changed (173) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +0 -0
  3. data/Rakefile +4 -0
  4. data/app/assets/images/rails.png +0 -0
  5. data/app/assets/javascripts/application.js +16 -0
  6. data/app/assets/javascripts/bootstrap_additions.js.coffee +4 -0
  7. data/app/assets/javascripts/interchange/patients.js.coffee +3 -0
  8. data/app/assets/javascripts/interchange/physicians.js.coffee +3 -0
  9. data/app/assets/javascripts/mock/allergies.js.coffee +3 -0
  10. data/app/assets/javascripts/mock/appointments.js.coffee +3 -0
  11. data/app/assets/javascripts/mock/assignments.js.coffee +17 -0
  12. data/app/assets/javascripts/mock/chart_reviews.js.coffee +3 -0
  13. data/app/assets/javascripts/mock/comments.js.coffee +3 -0
  14. data/app/assets/javascripts/mock/conditions.js.coffee +3 -0
  15. data/app/assets/javascripts/mock/diagnoses.js.coffee +3 -0
  16. data/app/assets/javascripts/mock/documents.js.coffee +3 -0
  17. data/app/assets/javascripts/mock/employments.js.coffee +3 -0
  18. data/app/assets/javascripts/mock/encounters.js.coffee +3 -0
  19. data/app/assets/javascripts/mock/family_contacts.js.coffee +3 -0
  20. data/app/assets/javascripts/mock/family_histories.js.coffee +3 -0
  21. data/app/assets/javascripts/mock/guarantors.js.coffee +3 -0
  22. data/app/assets/javascripts/mock/insurance_plans.js.coffee +3 -0
  23. data/app/assets/javascripts/mock/lab_concepts.js.coffee +4 -0
  24. data/app/assets/javascripts/mock/lab_results.js.coffee +3 -0
  25. data/app/assets/javascripts/mock/locations.js.coffee +3 -0
  26. data/app/assets/javascripts/mock/medical_record_numbers.js.coffee +3 -0
  27. data/app/assets/javascripts/mock/metadata_keywords.js.coffee +3 -0
  28. data/app/assets/javascripts/mock/pharmacies.js.coffee +3 -0
  29. data/app/assets/javascripts/mock/phone_numbers.js.coffee +3 -0
  30. data/app/assets/javascripts/mock/physicians.js.coffee +3 -0
  31. data/app/assets/javascripts/mock/procedure_histories.js.coffee +3 -0
  32. data/app/assets/javascripts/mock/providers.js.coffee +14 -0
  33. data/app/assets/javascripts/mock/questions.js.coffee +3 -0
  34. data/app/assets/javascripts/mock/reference_range.js.coffee +3 -0
  35. data/app/assets/javascripts/mock/sections.js.coffee +3 -0
  36. data/app/assets/javascripts/mock/social_histories.js.coffee +3 -0
  37. data/app/assets/javascripts/mock/state_health_identifiers.js.coffee +3 -0
  38. data/app/assets/javascripts/mock/statistics.js.coffee +3 -0
  39. data/app/assets/javascripts/mock/test_assertions.js.coffee +3 -0
  40. data/app/assets/javascripts/mock/visit.js.coffee +3 -0
  41. data/app/assets/javascripts/mock/vitals_measurement.js.coffee +3 -0
  42. data/app/assets/javascripts/reference/data_elements.js.coffee +3 -0
  43. data/app/assets/javascripts/reference/data_lists.js.coffee +3 -0
  44. data/app/assets/javascripts/reference/data_sets.js.coffee +3 -0
  45. data/app/assets/stylesheets/application.css.scss +13 -0
  46. data/app/assets/stylesheets/bootstrap_and_overrides.css.scss +79 -0
  47. data/app/assets/stylesheets/forms.css.scss +67 -0
  48. data/app/assets/stylesheets/interchange/patients.css.scss +3 -0
  49. data/app/assets/stylesheets/interchange/physicians.css.scss +3 -0
  50. data/app/assets/stylesheets/mock/allergies.css.scss +3 -0
  51. data/app/assets/stylesheets/mock/appointments.css.scss +3 -0
  52. data/app/assets/stylesheets/mock/chart_reviews.css.scss +3 -0
  53. data/app/assets/stylesheets/mock/comments.css.scss +3 -0
  54. data/app/assets/stylesheets/mock/conditions.css.scss +3 -0
  55. data/app/assets/stylesheets/mock/diagnoses.css.scss +3 -0
  56. data/app/assets/stylesheets/mock/documents.css.scss +3 -0
  57. data/app/assets/stylesheets/mock/employments.css.scss +3 -0
  58. data/app/assets/stylesheets/mock/encounters.css.scss +3 -0
  59. data/app/assets/stylesheets/mock/family_contacts.css.scss +3 -0
  60. data/app/assets/stylesheets/mock/family_histories.css.scss +3 -0
  61. data/app/assets/stylesheets/mock/guarantors.css.scss +3 -0
  62. data/app/assets/stylesheets/mock/insurance_plans.css.scss +3 -0
  63. data/app/assets/stylesheets/mock/lab_concepts.css.scss +3 -0
  64. data/app/assets/stylesheets/mock/lab_results.css.scss +3 -0
  65. data/app/assets/stylesheets/mock/locations.css.scss +3 -0
  66. data/app/assets/stylesheets/mock/medical_record_numbers.css.scss +3 -0
  67. data/app/assets/stylesheets/mock/metadata_keywords.css.scss +3 -0
  68. data/app/assets/stylesheets/mock/pharmacies.css.scss +3 -0
  69. data/app/assets/stylesheets/mock/phone_numbers.css.scss +3 -0
  70. data/app/assets/stylesheets/mock/physicians.css.scss +3 -0
  71. data/app/assets/stylesheets/mock/procedure_histories.css.scss +3 -0
  72. data/app/assets/stylesheets/mock/providers.css.scss +3 -0
  73. data/app/assets/stylesheets/mock/questions.css.scss +3 -0
  74. data/app/assets/stylesheets/mock/reference_range.css.scss +3 -0
  75. data/app/assets/stylesheets/mock/sections.css.scss +3 -0
  76. data/app/assets/stylesheets/mock/social_histories.css.scss +3 -0
  77. data/app/assets/stylesheets/mock/state_health_identifiers.css.scss +3 -0
  78. data/app/assets/stylesheets/mock/statistics.css.scss +3 -0
  79. data/app/assets/stylesheets/mock/test_assertions.css.scss +3 -0
  80. data/app/assets/stylesheets/mock/visit.css.scss +3 -0
  81. data/app/assets/stylesheets/mock/vitals_measurement.css.scss +3 -0
  82. data/app/assets/stylesheets/reference/data_elements.css.scss +3 -0
  83. data/app/assets/stylesheets/reference/data_lists.css.scss +3 -0
  84. data/app/assets/stylesheets/reference/data_sets.css.scss +3 -0
  85. data/app/assets/stylesheets/scaffolds.css.scss +66 -0
  86. data/app/controllers/api/base_controller.rb +78 -0
  87. data/app/controllers/api/ion_orders_engine/order_by_id/order_by_id_controller.rb +3220 -0
  88. data/app/controllers/api/ion_orders_engine/order_profile/inpatient_order_profile_controller.rb +3156 -0
  89. data/app/controllers/application_controller.rb +25 -0
  90. data/app/controllers/crud/base_controller.rb +90 -0
  91. data/app/controllers/interchange/base_controller.rb +63 -0
  92. data/app/controllers/interchange/data_sets_controller.rb +40 -0
  93. data/app/controllers/interchange/exports_controller.rb +120 -0
  94. data/app/controllers/interchange/imports_controller.rb +141 -0
  95. data/app/controllers/reference/base_controller.rb +7 -0
  96. data/app/controllers/reference/data_lists_controller.rb +177 -0
  97. data/app/controllers/reference/data_options_controller.rb +147 -0
  98. data/app/controllers/reference/data_sets_controller.rb +160 -0
  99. data/app/helpers/application_helper.rb +389 -0
  100. data/app/helpers/error_messages_helper.rb +23 -0
  101. data/app/helpers/interchange/exports_helper.rb +9 -0
  102. data/app/helpers/interchange/imports_helper.rb +31 -0
  103. data/app/helpers/layout_helper.rb +40 -0
  104. data/app/helpers/reference/data_elements_helper.rb +2 -0
  105. data/app/helpers/reference/data_lists_helper.rb +2 -0
  106. data/app/helpers/reference/data_sets_helper.rb +2 -0
  107. data/app/views/interchange/common/_database_info.json.jbuilder +6 -0
  108. data/app/views/interchange/common/_metadata_keywords.json.jbuilder +13 -0
  109. data/app/views/interchange/common/_test_assertions.json.jbuilder +17 -0
  110. data/app/views/interchange/data_sets/_data_list.json.jbuilder +14 -0
  111. data/app/views/interchange/data_sets/_data_option.json.jbuilder +12 -0
  112. data/app/views/interchange/data_sets/_data_set.json.jbuilder +17 -0
  113. data/app/views/interchange/data_sets/_nested_data_list.json.jbuilder +12 -0
  114. data/app/views/interchange/data_sets/show.json.jbuilder +10 -0
  115. data/app/views/interchange/document_templates/_document_template.json.jbuilder +23 -0
  116. data/app/views/interchange/document_templates/_section.json.jbuilder +11 -0
  117. data/app/views/interchange/document_templates/show.json.jbuilder +10 -0
  118. data/app/views/interchange/exports/_export_summary.html.erb +49 -0
  119. data/app/views/interchange/exports/show.html.erb +35 -0
  120. data/app/views/interchange/imports/_import_summary.html.erb +72 -0
  121. data/app/views/interchange/imports/show.html.erb +37 -0
  122. data/app/views/layouts/_flashbar.html.erb +6 -0
  123. data/app/views/layouts/_navbar.html.erb +38 -0
  124. data/app/views/layouts/_protected_warning.html.erb +7 -0
  125. data/app/views/layouts/_root_model_layout.erb +33 -0
  126. data/app/views/layouts/application.html.erb +39 -0
  127. data/app/views/layouts/reference/data_sets.html.erb +5 -0
  128. data/app/views/reference/data_lists/_data_options.html.erb +31 -0
  129. data/app/views/reference/data_lists/_form.html.erb +23 -0
  130. data/app/views/reference/data_lists/edit.html.erb +6 -0
  131. data/app/views/reference/data_lists/index.html.erb +31 -0
  132. data/app/views/reference/data_lists/new.html.erb +6 -0
  133. data/app/views/reference/data_lists/show.html.erb +55 -0
  134. data/app/views/reference/data_options/_form.html.erb +23 -0
  135. data/app/views/reference/data_options/edit.html.erb +5 -0
  136. data/app/views/reference/data_options/index.html.erb +38 -0
  137. data/app/views/reference/data_options/new.html.erb +5 -0
  138. data/app/views/reference/data_options/show.html.erb +33 -0
  139. data/app/views/reference/data_sets/_form.html.erb +25 -0
  140. data/app/views/reference/data_sets/edit.html.erb +5 -0
  141. data/app/views/reference/data_sets/index.html.erb +40 -0
  142. data/app/views/reference/data_sets/new.html.erb +5 -0
  143. data/app/views/reference/data_sets/show.html.erb +38 -0
  144. data/config/application.rb +100 -0
  145. data/config/boot.rb +6 -0
  146. data/config/database.yml +25 -0
  147. data/config/environment.rb +5 -0
  148. data/config/environments/development.rb +42 -0
  149. data/config/environments/production.rb +64 -0
  150. data/config/environments/test.rb +35 -0
  151. data/config/initializers/backtrace_silencers.rb +7 -0
  152. data/config/initializers/extensions/active_record.rb +13 -0
  153. data/config/initializers/extensions/hash.rb +11 -0
  154. data/config/initializers/extensions/string.rb +15 -0
  155. data/config/initializers/inflections.rb +15 -0
  156. data/config/initializers/mime_types.rb +5 -0
  157. data/config/initializers/reference.rb +77 -0
  158. data/config/initializers/secret_token.rb +7 -0
  159. data/config/initializers/session_store.rb +8 -0
  160. data/config/initializers/simple_form.rb +142 -0
  161. data/config/initializers/simple_form_bootstrap.rb +45 -0
  162. data/config/initializers/wrap_parameters.rb +10 -0
  163. data/config/locales/en.yml +207 -0
  164. data/config/locales/simple_form.en.yml +26 -0
  165. data/config/mongo.yml +18 -0
  166. data/config/routes.rb +4 -0
  167. data/db/schema.rb +16 -0
  168. data/db/seeds.rb +66 -0
  169. data/lib/ion_orders_engine_mockingjay/engine.rb +13 -0
  170. data/lib/ion_orders_engine_mockingjay/version.rb +3 -0
  171. data/lib/ion_orders_engine_mockingjay.rb +4 -0
  172. data/lib/tasks/ion_orders_engine_mockingjay_tasks.rake +4 -0
  173. 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,7 @@
1
+ class Reference::BaseController < Crud::BaseController
2
+
3
+ def module_symbol_for_paths
4
+ :reference
5
+ end
6
+
7
+ end
@@ -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