osc_machete_rails 1.2.0

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 (113) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +76 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +14 -0
  5. data/Rakefile +34 -0
  6. data/app/assets/javascripts/osc_machete_rails/application.js +13 -0
  7. data/app/assets/stylesheets/osc_machete_rails/application.css +13 -0
  8. data/app/controllers/osc_machete_rails/application_controller.rb +4 -0
  9. data/app/helpers/osc_machete_rails/application_helper.rb +4 -0
  10. data/app/views/layouts/osc_machete_rails/application.html.erb +14 -0
  11. data/config/routes.rb +2 -0
  12. data/lib/generators/active_record/job_model_generator.rb +13 -0
  13. data/lib/generators/active_record/orm_helpers.rb +6 -0
  14. data/lib/generators/active_record/templates/job_model.rb +17 -0
  15. data/lib/generators/active_record/templates/migration.rb +19 -0
  16. data/lib/generators/active_record/templates/module.rb +7 -0
  17. data/lib/generators/active_record/templates/workflow_model.rb +34 -0
  18. data/lib/generators/active_record/workflow_model_generator.rb +30 -0
  19. data/lib/generators/osc_machete_rails/USAGE +36 -0
  20. data/lib/generators/osc_machete_rails/erb/erb_generator.rb +5 -0
  21. data/lib/generators/osc_machete_rails/erb/templates/_form.html.erb +21 -0
  22. data/lib/generators/osc_machete_rails/erb/templates/edit.html.erb +5 -0
  23. data/lib/generators/osc_machete_rails/erb/templates/index.html.erb +41 -0
  24. data/lib/generators/osc_machete_rails/erb/templates/new.html.erb +5 -0
  25. data/lib/generators/osc_machete_rails/erb/templates/show.html.erb +13 -0
  26. data/lib/generators/osc_machete_rails/job_helpers.rb +10 -0
  27. data/lib/generators/osc_machete_rails/job_model/USAGE +28 -0
  28. data/lib/generators/osc_machete_rails/job_model/job_model_generator.rb +13 -0
  29. data/lib/generators/osc_machete_rails/resource_route/USAGE +3 -0
  30. data/lib/generators/osc_machete_rails/resource_route/resource_route_generator.rb +57 -0
  31. data/lib/generators/osc_machete_rails/scaffold_controller/USAGE +17 -0
  32. data/lib/generators/osc_machete_rails/scaffold_controller/scaffold_controller_generator.rb +24 -0
  33. data/lib/generators/osc_machete_rails/scaffold_controller/templates/controller.rb +120 -0
  34. data/lib/generators/osc_machete_rails/scaffold_generator.rb +35 -0
  35. data/lib/generators/osc_machete_rails/workflow_model/USAGE +38 -0
  36. data/lib/generators/osc_machete_rails/workflow_model/workflow_model_generator.rb +12 -0
  37. data/lib/generators/osc_machete_rails/workflow_template/USAGE +19 -0
  38. data/lib/generators/osc_machete_rails/workflow_template/templates/main.sh.mustache +18 -0
  39. data/lib/generators/osc_machete_rails/workflow_template/workflow_template_generator.rb +9 -0
  40. data/lib/osc_machete_rails/engine.rb +24 -0
  41. data/lib/osc_machete_rails/helper.rb +25 -0
  42. data/lib/osc_machete_rails/statusable.rb +199 -0
  43. data/lib/osc_machete_rails/version.rb +3 -0
  44. data/lib/osc_machete_rails/workflow.rb +249 -0
  45. data/lib/osc_machete_rails.rb +12 -0
  46. data/lib/tasks/osc_machete_rails_tasks.rake +4 -0
  47. data/test/dummy/README.rdoc +28 -0
  48. data/test/dummy/Rakefile +6 -0
  49. data/test/dummy/app/assets/javascripts/application.js +13 -0
  50. data/test/dummy/app/assets/javascripts/simulations.js +2 -0
  51. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  52. data/test/dummy/app/assets/stylesheets/simulations.css +4 -0
  53. data/test/dummy/app/controllers/application_controller.rb +5 -0
  54. data/test/dummy/app/controllers/simulations_controller.rb +103 -0
  55. data/test/dummy/app/helpers/application_helper.rb +2 -0
  56. data/test/dummy/app/helpers/simulations_helper.rb +2 -0
  57. data/test/dummy/app/models/simulation.rb +26 -0
  58. data/test/dummy/app/models/simulation_job.rb +15 -0
  59. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  60. data/test/dummy/app/views/simulations/_form.html.erb +15 -0
  61. data/test/dummy/app/views/simulations/edit.html.erb +5 -0
  62. data/test/dummy/app/views/simulations/index.html.erb +35 -0
  63. data/test/dummy/app/views/simulations/new.html.erb +5 -0
  64. data/test/dummy/app/views/simulations/show.html.erb +16 -0
  65. data/test/dummy/bin/bundle +3 -0
  66. data/test/dummy/bin/rails +4 -0
  67. data/test/dummy/bin/rake +4 -0
  68. data/test/dummy/config/application.rb +23 -0
  69. data/test/dummy/config/boot.rb +5 -0
  70. data/test/dummy/config/database.yml +25 -0
  71. data/test/dummy/config/environment.rb +5 -0
  72. data/test/dummy/config/environments/development.rb +29 -0
  73. data/test/dummy/config/environments/production.rb +80 -0
  74. data/test/dummy/config/environments/test.rb +36 -0
  75. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  76. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  77. data/test/dummy/config/initializers/inflections.rb +16 -0
  78. data/test/dummy/config/initializers/mime_types.rb +5 -0
  79. data/test/dummy/config/initializers/secret_token.rb +12 -0
  80. data/test/dummy/config/initializers/session_store.rb +3 -0
  81. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  82. data/test/dummy/config/locales/en.yml +23 -0
  83. data/test/dummy/config/routes.rb +11 -0
  84. data/test/dummy/config.ru +4 -0
  85. data/test/dummy/db/development.sqlite3 +0 -0
  86. data/test/dummy/db/migrate/20151230193910_create_simulations.rb +11 -0
  87. data/test/dummy/db/migrate/20151230193911_create_simulation_jobs.rb +15 -0
  88. data/test/dummy/db/schema.rb +38 -0
  89. data/test/dummy/db/test.sqlite3 +0 -0
  90. data/test/dummy/jobs/simulation/main.sh.mustache +17 -0
  91. data/test/dummy/log/development.log +0 -0
  92. data/test/dummy/log/test.log +31198 -0
  93. data/test/dummy/public/404.html +58 -0
  94. data/test/dummy/public/422.html +58 -0
  95. data/test/dummy/public/500.html +57 -0
  96. data/test/dummy/public/favicon.ico +0 -0
  97. data/test/dummy/tmp/cache/assets/test/sprockets/0ff4cb4a6c217771a1336b307c51cf4e +0 -0
  98. data/test/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  99. data/test/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  100. data/test/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  101. data/test/dummy/tmp/cache/assets/test/sprockets/57261b7c75c19be33229517e39e47528 +0 -0
  102. data/test/dummy/tmp/cache/assets/test/sprockets/9e1e594361ba2561e5f6011db99503bb +0 -0
  103. data/test/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  104. data/test/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  105. data/test/dummy/tmp/cache/assets/test/sprockets/dc292ec300d07016ebcc2de4806208c3 +0 -0
  106. data/test/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  107. data/test/integration/error_handling_test.rb +166 -0
  108. data/test/integration/statusable_update_status_test.rb +47 -0
  109. data/test/models/simulation_test.rb +4 -0
  110. data/test/osc_machete_rails_test.rb +7 -0
  111. data/test/test_helper.rb +19 -0
  112. data/test/unit/statusable_test.rb +124 -0
  113. metadata +320 -0
@@ -0,0 +1,249 @@
1
+ module OscMacheteRails
2
+ # A plugin to maintain a workflow for Jobs.
3
+ module Workflow
4
+
5
+ # Registers a workflow relationship and sets up a hook to additional builder methods.
6
+ #
7
+ # @param [Symbol] jobs_active_record_relation_symbol The Job Identifier
8
+ def has_machete_workflow_of(jobs_active_record_relation_symbol)
9
+ # yes, this is magic mimicked from http://guides.rubyonrails.org/plugins.html
10
+ # and http://yehudakatz.com/2009/11/12/better-ruby-idioms/
11
+ cattr_accessor :jobs_active_record_relation_symbol
12
+ self.jobs_active_record_relation_symbol = jobs_active_record_relation_symbol
13
+
14
+ # separate modules to group common methods for readability purposes
15
+ # both builder methods and status methods need the jobs relation so
16
+ # we include that first
17
+ self.send :include, OscMacheteRails::Workflow::JobsRelation
18
+ self.send :include, OscMacheteRails::Workflow::BuilderMethods
19
+ self.send :include, OscMacheteRails::Workflow::StatusMethods
20
+ end
21
+
22
+ # The module defining the active record relation of the jobs
23
+ module JobsRelation
24
+ # Assign the active record relation of this instance to the
25
+ def jobs_active_record_relation
26
+ self.send self.class.jobs_active_record_relation_symbol
27
+ end
28
+ end
29
+
30
+ # depends on jobs_active_record_relation being defined
31
+ module BuilderMethods
32
+ # Methods run when this module is included
33
+ def self.included(obj)
34
+ # before we destroy ActiveRecord we stop all jobs and delete staging dir
35
+ # prepend: true tells this to run before any of the jobs are destroyed
36
+ # so we can stop them first and recover if there is a problem
37
+ if obj.respond_to?(:before_destroy)
38
+ obj.before_destroy prepend: true do |sim|
39
+ sim.stop ? sim.delete_staging : false
40
+ end
41
+ end
42
+ end
43
+
44
+ def ood_dataroot
45
+ if defined? OodAppkit
46
+ OodAppkit.dataroot
47
+ elsif ENV['OOD_DATAROOT'] || ENV['RAILS_DATAROOT']
48
+ Pathname.new(ENV['OOD_DATAROOT'] || ENV['RAILS_DATAROOT'])
49
+ else
50
+ raise "no ood_dataroot specified"
51
+ end
52
+ end
53
+
54
+ #
55
+ # @example Underscore a class
56
+ # FlowratePerformanceRun => flowrate_performance_run
57
+ #
58
+ # @return [String] The template name
59
+ def staging_template_name
60
+ self.class.name.underscore
61
+ end
62
+
63
+ # Returns the name of a staging directory that has been underscored and pluralized.
64
+ #
65
+ # @example
66
+ # Simulation => simulations
67
+ # @example
68
+ # FlowratePerformanceRun => flowrate_performance_runs
69
+ #
70
+ # @return [String] The staging template directory name
71
+ def staging_target_dir_name
72
+ staging_template_name.pluralize
73
+ end
74
+
75
+ # Gets the staging target directory path.
76
+ # Joins the AwesimRails.dataroot and the staging target directory name.
77
+ #
78
+ # @raise [Exception] "override staging_target_dir or include awesim_rails gem"
79
+ #
80
+ # @return [String] The staging target directory path.
81
+ def staging_target_dir(dataroot: ood_dataroot)
82
+ Pathname.new(dataroot).join(staging_target_dir_name)
83
+ end
84
+
85
+ # Gets the staging template directory path.
86
+ # Joins the { rails root }/jobs/{ staging_template_name } into a path.
87
+ #
88
+ # @return [String] The staging template directory path.
89
+ def staging_template_dir
90
+ Rails.root.join("jobs", staging_template_name)
91
+ end
92
+
93
+ # Creates a new staging target job directory on the system
94
+ # Copies the staging template directory to the staging target job directory
95
+ #
96
+ # @return [Pathname] The staged directory path.
97
+ def stage
98
+ staged_dir = OSC::Machete::JobDir.new(staging_target_dir).new_jobdir
99
+ FileUtils.mkdir_p staged_dir
100
+ FileUtils.cp_r staging_template_dir.to_s + "/.", staged_dir
101
+
102
+ staged_dir
103
+ end
104
+
105
+ # Deletes the staged directory if it exists
106
+ def delete_staging
107
+ FileUtils.rm_rf(staged_dir) if respond_to?(:staged_dir) && staged_dir
108
+ end
109
+
110
+ # Stops all jobs, updating each active job to status "failed"
111
+ # returns true if all jobs were stopped, false otherwise
112
+ def stop
113
+ jobs_active_record_relation.to_a.each(&:stop)
114
+
115
+ true
116
+ rescue PBS::Error => e
117
+ msg = "A PBS::Error occurred when trying to stop jobs for simulation #{id}: #{e.message}"
118
+ errors[:base] << msg
119
+ Rails.logger.error(msg)
120
+
121
+ false
122
+ end
123
+
124
+ # Creates a new location and renders the mustache files
125
+ #
126
+ # @param [String] staged_dir The staging target directory path.
127
+ # @param [Hash] template_view The template options to be rendered.
128
+ #
129
+ # @return [Location] The location of the staged and rendered template.
130
+ def render_mustache_files(staged_dir, template_view)
131
+ OSC::Machete::Location.new(staged_dir).render(template_view)
132
+ end
133
+
134
+ # Actions to perform after staging
135
+ #
136
+ # @param [String] staged_dir The staged directory path.
137
+ def after_stage(staged_dir)
138
+ end
139
+
140
+ # Unimplemented method for building jobs.
141
+ #
142
+ # @param [String] staged_dir The staged directory path.
143
+ # @param [Array, Nil] jobs An array of jobs to be built.
144
+ #
145
+ # @raise [NotImplementedError] The method is currently not implemented
146
+ def build_jobs(staged_dir, jobs = [])
147
+ raise NotImplementedError, "Objects including OSC::Machete::SimpleJob::Workflow must implement build_jobs"
148
+ end
149
+
150
+ # Call the #submit method on each job in a hash.
151
+ #
152
+ # @param [Hash] jobs A Hash of Job objects to be submitted.
153
+ def submit_jobs(jobs)
154
+ jobs.each(&:submit)
155
+ true
156
+ rescue OSC::Machete::Job::ScriptMissingError => e
157
+ stop_machete_jobs(jobs)
158
+
159
+ msg = "A OSC::Machete::Job::ScriptMissingError occurred when submitting jobs for simulation #{id}: #{e.message}"
160
+ errors[:base] << msg
161
+ Rails.logger.error(msg)
162
+ false
163
+ rescue PBS::Error => e
164
+ stop_machete_jobs(jobs)
165
+
166
+ msg = "A PBS::Error occurred when submitting jobs for simulation #{id}: #{e.message}"
167
+ errors[:base] << msg
168
+ Rails.logger.error(msg)
169
+
170
+ false
171
+ end
172
+
173
+ # given an array of OSC::Machete::Job objects, qdel them all and handle
174
+ # any errors. not to be confused with #stop which stops all actual jobs of
175
+ # the workflow
176
+ def stop_machete_jobs(jobs)
177
+ jobs.each do |job|
178
+ begin
179
+ job.delete
180
+ rescue PBS::Error
181
+ msg = "A PBS::Error occurred when deleting a job from the batch system with pbsid: #{job.pbsid} and message: #{e.message}"
182
+ errors[:base] << msg
183
+ Rails.logger.error(msg)
184
+ end
185
+ end
186
+ end
187
+
188
+ # Saves a Hash of jobs to a staged directory
189
+ #
190
+ # @param [Hash] jobs A Hash of Job objects to be saved.
191
+ # @param [Location] staged_dir The staged directory as Location object.
192
+ def save_jobs(jobs, staged_dir)
193
+ self.staged_dir = staged_dir.to_s if self.respond_to?(:staged_dir=)
194
+ self.save if self.id.nil? || self.respond_to?(:staged_dir=)
195
+
196
+ jobs.each do |job|
197
+ self.jobs_active_record_relation.create(job: job)
198
+ end
199
+ end
200
+
201
+ # Perform the submit actions.
202
+ #
203
+ # Sets the staged_dir
204
+ # Renders the mustache files.
205
+ # Calls after_stage.
206
+ # Calls build_jobs.
207
+ # Submits the jobs.
208
+ # Saves the jobs.
209
+ #
210
+ # @param [Hash, nil] template_view (self) The template options to be rendered.
211
+ def submit(template_view=self)
212
+ staged_dir = stage
213
+ render_mustache_files(staged_dir, template_view)
214
+ after_stage(staged_dir)
215
+ jobs = build_jobs(staged_dir)
216
+ if submit_jobs(jobs)
217
+ save_jobs(jobs, staged_dir)
218
+ else
219
+ FileUtils.rm_rf staged_dir.to_s
220
+ false
221
+ end
222
+ end
223
+ end
224
+
225
+ # depends on jobs_active_record_relation being defined
226
+ module StatusMethods
227
+ delegate :not_submitted?, :submitted?, :completed?, :passed?, :failed?, :active?, to: :status
228
+
229
+ # Reduce the jobs to a single OSC::Machete:Status value
230
+ #
231
+ # Assumes `jobs_active_record_relation` is a Statusable ActiveRecord
232
+ # model. Get array of status values (one for each job) and then add them
233
+ # together to get one value. OSC::Machete::Status#+ is overridden to
234
+ # return the highest precendent status value when adding two together.
235
+ #
236
+ # FIXME: it might be clearer in code to use `max` instead of `+` i.e.
237
+ # statuses.reduce(&:max) and rename OSC::Machete::Status#+.
238
+ #
239
+ # @return [OSC::Machete::Status] a single value representing the status
240
+ def status
241
+ statuses = jobs_active_record_relation.to_a.map(&:status)
242
+ statuses.empty? ? OSC::Machete::Status.not_submitted : statuses.reduce(&:+)
243
+ end
244
+ end
245
+
246
+ # extend Active Record with the has_workflow_of method
247
+ ActiveRecord::Base.extend OscMacheteRails::Workflow if defined? ActiveRecord::Base
248
+ end
249
+ end
@@ -0,0 +1,12 @@
1
+ require "osc/machete"
2
+ require "osc_machete_rails/engine"
3
+ require "osc_machete_rails/statusable"
4
+ require "osc_machete_rails/workflow"
5
+ require "osc_machete_rails/helper"
6
+
7
+ module OscMacheteRails
8
+ mattr_accessor :update_status_of_all_active_jobs_on_each_request
9
+
10
+ # make OSC::Machete::SimpleJob an alias of this module for backwards compatibility
11
+ OSC::Machete::SimpleJob = self
12
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :osc_machete_rails do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,28 @@
1
+ == README
2
+
3
+ This README would normally document whatever steps are necessary to get the
4
+ application up and running.
5
+
6
+ Things you may want to cover:
7
+
8
+ * Ruby version
9
+
10
+ * System dependencies
11
+
12
+ * Configuration
13
+
14
+ * Database creation
15
+
16
+ * Database initialization
17
+
18
+ * How to run the test suite
19
+
20
+ * Services (job queues, cache servers, search engines, etc.)
21
+
22
+ * Deployment instructions
23
+
24
+ * ...
25
+
26
+
27
+ Please feel free to use a different markup language if you do not plan to run
28
+ <tt>rake doc:app</tt>.
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Dummy::Application.load_tasks
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,5 @@
1
+ class ApplicationController < ActionController::Base
2
+ # Prevent CSRF attacks by raising an exception.
3
+ # For APIs, you may want to use :null_session instead.
4
+ protect_from_forgery with: :exception
5
+ end
@@ -0,0 +1,103 @@
1
+ class SimulationsController < ApplicationController
2
+ before_action :set_simulation, only: [:show, :edit, :update, :destroy, :submit, :copy]
3
+
4
+ # GET /simulations
5
+ # GET /simulations.json
6
+ def index
7
+ @simulations = Simulation.preload(:simulation_jobs).all
8
+ end
9
+
10
+ # GET /simulations/1
11
+ # GET /simulations/1.json
12
+ def show
13
+ end
14
+
15
+ # GET /simulations/new
16
+ def new
17
+ @simulation = Simulation.new
18
+ end
19
+
20
+ # GET /simulations/1/edit
21
+ def edit
22
+ end
23
+
24
+ # POST /simulations
25
+ # POST /simulations.json
26
+ def create
27
+ @simulation = Simulation.new(simulation_params)
28
+
29
+ respond_to do |format|
30
+ if @simulation.save
31
+ format.html { redirect_to @simulation, notice: 'Simulation was successfully created.' }
32
+ format.json { render :show, status: :created, location: @simulation }
33
+ else
34
+ format.html { render :new }
35
+ format.json { render json: @simulation.errors, status: :unprocessable_entity }
36
+ end
37
+ end
38
+ end
39
+
40
+ # PATCH/PUT /simulations/1
41
+ # PATCH/PUT /simulations/1.json
42
+ def update
43
+ respond_to do |format|
44
+ if @simulation.update(simulation_params)
45
+ format.html { redirect_to @simulation, notice: 'Simulation was successfully updated.' }
46
+ format.json { render :show, status: :ok, location: @simulation }
47
+ else
48
+ format.html { render :edit }
49
+ format.json { render json: @simulation.errors, status: :unprocessable_entity }
50
+ end
51
+ end
52
+ end
53
+
54
+ # DELETE /simulations/1
55
+ # DELETE /simulations/1.json
56
+ def destroy
57
+ respond_to do |format|
58
+ if @simulation.destroy
59
+ format.html { redirect_to simulations_url, notice: 'Simulation was successfully destroyed.' }
60
+ format.json { head :no_content }
61
+ else
62
+ format.html { render :show, status: 500, alert: 'A problem occurred when trying to destroy the simulation.' }
63
+ format.json { render json: @simulation.errors, status: 500 }
64
+ end
65
+ end
66
+ end
67
+
68
+ # PUT /simulations/1/submit
69
+ # PUT /simulations/1/submit.json
70
+ def submit
71
+ respond_to do |format|
72
+
73
+ if @simulation.submitted?
74
+ format.html { redirect_to simulations_url, alert: 'Simulation has already been submitted.' }
75
+ format.json { head :no_content }
76
+ elsif @simulation.submit
77
+ format.html { redirect_to simulations_url, notice: 'Simulation was successfully submitted.' }
78
+ format.json { head :no_content }
79
+ else
80
+ format.html { render :show, status: 500, alert: 'A problem occurred when trying to submit the simulation.' }
81
+ format.json { render json: @simulation.errors, status: 500 }
82
+ end
83
+ end
84
+ end
85
+
86
+ # PUT /simulations/1/copy
87
+ def copy
88
+ @simulation = @simulation.copy
89
+
90
+ render template: "simulations/edit"
91
+ end
92
+
93
+ private
94
+ # Use callbacks to share common setup or constraints between actions.
95
+ def set_simulation
96
+ @simulation = Simulation.preload(:simulation_jobs).find(params[:id])
97
+ end
98
+
99
+ # Only allow a trusted parameter "white list" through.
100
+ def simulation_params
101
+ params.require(:simulation).permit!
102
+ end
103
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ module SimulationsHelper
2
+ end
@@ -0,0 +1,26 @@
1
+ class Simulation < ActiveRecord::Base
2
+ has_many :simulation_jobs, dependent: :destroy
3
+ has_machete_workflow_of :simulation_jobs
4
+
5
+
6
+ # Name that defines the template/target dirs
7
+ def staging_template_name
8
+ "simulation"
9
+ end
10
+
11
+ # Define tasks to do after staging template directory typically copy over
12
+ # uploaded files here
13
+ # def after_stage(staged_dir)
14
+ # # CODE HERE
15
+ # end
16
+
17
+ # Build an array of Machete jobs that are then submitted to the batch server
18
+ def build_jobs(staged_dir, job_list = [])
19
+ job_list << OSC::Machete::Job.new(script: staged_dir.join("main.sh"))
20
+ end
21
+
22
+ # Make copy of workflow
23
+ def copy
24
+ self.dup
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ class SimulationJob < ActiveRecord::Base
2
+ # Here we test the deprecated include method instead of the new
3
+ # OscMacheteRails::Statusable
4
+ # We will want both to work...
5
+ include OSC::Machete::SimpleJob::Statusable
6
+
7
+ belongs_to :simulation
8
+
9
+ before_destroy { |j| j.job.delete(rmdir: true) if j.job }
10
+
11
+ # Determine if the results are valid
12
+ # def results_valid?
13
+ # # CODE GOES HERE
14
+ # end
15
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
6
+ <%= javascript_include_tag "application", "data-turbolinks-track" => true %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
@@ -0,0 +1,15 @@
1
+ <%# Uses rails_bootstrap_form gem. API at: https://github.com/bootstrap-ruby/rails-bootstrap-forms %>
2
+ <%= bootstrap_form_for(simulation) do |f| %>
3
+ <%= f.alert_message "Please fix the errors below." %>
4
+
5
+ <%= f.text_field :name %>
6
+ <%= f.text_field :pressure %>
7
+
8
+ <%= f.submit 'Save', class: 'btn btn-primary' %>
9
+ <%= f.button 'Reset', type: :reset, class: 'btn btn-default' %>
10
+
11
+ <hr>
12
+
13
+ <%= link_to 'Back', simulations_path, class: 'btn btn-default' %>
14
+ <%= link_to 'Show', simulation, class: 'btn btn-primary' unless simulation.new_record? %>
15
+ <% end %>
@@ -0,0 +1,5 @@
1
+ <div class="page-header">
2
+ <h2>Editing Simulation</h2>
3
+ </div>
4
+
5
+ <%= render 'form', simulation: @simulation %>
@@ -0,0 +1,35 @@
1
+ <div class="page-header">
2
+ <h2>Listing Simulations</h2>
3
+ </div>
4
+
5
+ <table class="table">
6
+ <thead>
7
+ <tr>
8
+ <th>#</th>
9
+ <th>Status</th>
10
+ <th>Name</th>
11
+ <th>Pressure</th>
12
+ <th colspan="4"></th>
13
+ </tr>
14
+ </thead>
15
+
16
+ <tbody>
17
+ <% @simulations.each do |simulation| %>
18
+ <tr>
19
+ <td><%= simulation.id %></td>
20
+ <td><%= status_label(simulation) %></td>
21
+ <td><%= simulation.name %></td>
22
+ <td><%= simulation.pressure %></td>
23
+ <td><%= link_to 'Submit', submit_simulation_path(simulation), method: :put, class: 'btn btn-success btn-sm' unless simulation.submitted? %></td>
24
+ <td><%= link_to 'Show', simulation, class: 'btn btn-primary btn-sm' %></td>
25
+ <td><%= link_to 'Edit', edit_simulation_path(simulation), class: 'btn btn-default btn-sm' unless simulation.submitted? %></td>
26
+ <td><%= link_to 'Copy', copy_simulation_path(simulation), method: :put, class: 'btn btn-default btn-sm' %></td>
27
+ <td><%= link_to 'Destroy', simulation, method: :delete, class: 'btn btn-danger btn-sm', data: { confirm: 'Are you sure?' } %></td>
28
+ </tr>
29
+ <% end %>
30
+ </tbody>
31
+ </table>
32
+
33
+ <br>
34
+
35
+ <%= link_to 'New Simulation', new_simulation_path %>
@@ -0,0 +1,5 @@
1
+ <div class="page-header">
2
+ <h2>New Simulation</h2>
3
+ </div>
4
+
5
+ <%= render 'form', simulation: @simulation %>
@@ -0,0 +1,16 @@
1
+ <div class="page-header">
2
+ <h2>Showing Simulation</h2>
3
+ </div>
4
+
5
+ <p>
6
+ <strong>Name:</strong>
7
+ <%= @simulation.name %>
8
+ </p>
9
+
10
+ <p>
11
+ <strong>Pressure:</strong>
12
+ <%= @simulation.pressure %>
13
+ </p>
14
+
15
+ <%= link_to 'Back', simulations_path, class: 'btn btn-default' %>
16
+ <%= link_to 'Edit', edit_simulation_path(@simulation), class: 'btn btn-default' %>
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
+ load Gem.bin_path('bundler', 'bundle')
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
3
+ require_relative '../config/boot'
4
+ require 'rails/commands'
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require_relative '../config/boot'
3
+ require 'rake'
4
+ Rake.application.run
@@ -0,0 +1,23 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require 'rails/all'
4
+
5
+ Bundler.require(*Rails.groups)
6
+ require "osc_machete_rails"
7
+
8
+ module Dummy
9
+ class Application < Rails::Application
10
+ # Settings in config/environments/* take precedence over those specified here.
11
+ # Application configuration should go into files in config/initializers
12
+ # -- all .rb files in that directory are automatically loaded.
13
+
14
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
15
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
16
+ # config.time_zone = 'Central Time (US & Canada)'
17
+
18
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
19
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
20
+ # config.i18n.default_locale = :de
21
+ end
22
+ end
23
+
@@ -0,0 +1,5 @@
1
+ # Set up gems listed in the Gemfile.
2
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
3
+
4
+ require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
5
+ $LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__)