osc_machete_rails 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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__)