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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8fd50095c5fcd06e3563aaaed87004a06c9e76aa
4
+ data.tar.gz: c0b622235dee4361de6467d929f352d875905c24
5
+ SHA512:
6
+ metadata.gz: 38d903278baf2add66f71037dbb192b15a65b75b019eb2f9ba080e2a110cb9d014d0b1c59aa0231ef048a0277211f919da9643b2763cf9994d0cbf63ac6477fc
7
+ data.tar.gz: 84231e28bb943ea11a0cbde8ca6325c0ac89ed6b0ec882ce7b5be6e3150a7a4591adf4a7a6a204e019eaf327449547a3d54ffea1b110ba53106f3a1f1a3f6b0b
data/CHANGELOG.md ADDED
@@ -0,0 +1,76 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ This project adheres to [Semantic Versioning](http://semver.org/).
5
+
6
+ ## [Unreleased]
7
+
8
+ ### Changed
9
+
10
+ - remove `AwesimRails` as a dependency
11
+
12
+ ## [1.1.0] - 2016-03-03
13
+
14
+ ### Fixed
15
+
16
+ - fix precompiling assets when a database is not available (which almost always happens when you go to share an app)
17
+
18
+ ### Changed
19
+
20
+ - status_label view helper now accepts a second optional argument specifying the tag that wraps the label (defaults to span)
21
+ - status_label view helper now adds the class `status_label` to the labels for easier customization of the labels
22
+
23
+ ## [1.0.1] - 2016-02-19
24
+
25
+ ### Fixed
26
+
27
+ - Fix module used so Statusable.update_status_of_all_active_jobs is called on each request
28
+
29
+ ## 1.0.0 - 2016-02-03
30
+
31
+ This release notes changes from existing files pulled out of osc-machete gem and
32
+ added features and fixed defects that this gem introduces.
33
+
34
+ ### Fixed
35
+
36
+ - `update_status!` on the `Job` models (models that include `OscMacheteRails::Statusable`) is called at beginning of each request instead of in the `after_find` hook, so you no longer need to preload to trigger the update (a big hangup we had earlier for each new developer)
37
+ - even if you did preload for the `Job` models, superfluous sql calls were being made for each model - this was eliminated
38
+ - with the latest version of torque new status values were causing problems with status display on simulations. Introducing the Status value object fixed this problem
39
+ - proper error handling avoided various odd behavior that resulted if job submission failed
40
+
41
+ ### Added
42
+
43
+ - Rails generators to scaffold a workflow
44
+ - status_label helper to replace the one previously manually added or generated by Rails application template (this one handles Status values appropriately)
45
+ - Initialization option: change OscMacheteRails.update_status_of_all_active_jobs_on_each_request to false if you want to disable the update of all active jobs on each request
46
+ - workflow.rb: before_destroy we stop all of the jobs and if that succeeds we delete the staged directory if "staged_dir" exists on model that has a workflow
47
+ - statusable.rb: Added Statusable#stop to allow qdel-ing the job. This could be used to implement a stop feature if you wanted to stop a simulation but keep from deleting the files it had created so far.
48
+
49
+
50
+ ### Changed
51
+
52
+ workflow.rb (from v0.6.3 of osc-machete to latest osc_machete_rails)
53
+
54
+ - in module OscMacheteRails instead of OSC::Machete::SimpleJob
55
+ - handle errors when submitting jobs, logging the error and setting it on the model#errors object
56
+ - if submitting a job fails, we delete the staged directory that was created during submission
57
+
58
+ statusable.rb (from v0.6.3 of osc-machete to latest osc_machete_rails)
59
+
60
+ - in module OscMacheteRails instead of OSC::Machete::SimpleJob
61
+ - models that include Statutable no longer are updated via after_find hook. instead a new class method "update_status_of_all_active_jobs" is called to call `Statusable#update_status!` on each instance that is in an active state (running, queued, etc.). this is called at the beginning of each request via a before_action hook on the application controller.
62
+ - update_status! handles PBS::Error's when checking the status, logs an error in the log and then leaves the model untouched
63
+ - Statusable#status returns OSC::Machete::Status object instead of a character
64
+ - Statusable#status= can accept a character, nil or an OSC::Machete::Status
65
+ - Statusable#job= lets you set the attributes of an OSC::Machete::Job object to the Statusable model. Backwards compatibility supports saving the attributes script_name, job_path, and pbsid. New models produced by the generators use a job_cache column that stores a hash, and script, pbsid, and host are saved here instead.
66
+ - setters `script_name=` and `job_path=` do not exist on models that are generated using the generators (models that have a job_cache column)
67
+
68
+
69
+
70
+ ### Removed
71
+
72
+
73
+ [Unreleased]: https://github.com/AweSim-OSC/osc_machete_rails/compare/v1.1.0...master
74
+ [1.1.0]: https://github.com/AweSim-OSC/osc_machete_rails/compare/v1.0.1...v1.1.0
75
+ [1.0.1]: https://github.com/AweSim-OSC/osc_machete_rails/compare/v1.0.0...v1.0.1
76
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015-2016 Ohio Supercomputer Center
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # OscMacheteRails
2
+
3
+ Build and manage simulation workflows.
4
+
5
+ ## Installation
6
+
7
+ To use, add this line to your application's Gemfile:
8
+
9
+ gem 'osc_machete_rails'
10
+
11
+ And then execute:
12
+
13
+ $ bundle install
14
+
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'OscMacheteRails'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -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,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
+ module OscMacheteRails
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module OscMacheteRails
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>OscMacheteRails</title>
5
+ <%= stylesheet_link_tag "osc_machete_rails/application", media: "all" %>
6
+ <%= javascript_include_tag "osc_machete_rails/application" %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ OscMacheteRails::Engine.routes.draw do
2
+ end
@@ -0,0 +1,13 @@
1
+ require 'rails/generators/active_record/model/model_generator'
2
+ require 'generators/active_record/orm_helpers'
3
+
4
+ class ActiveRecord::JobModelGenerator < ActiveRecord::Generators::ModelGenerator
5
+ include ActiveRecord::OrmHelpers
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ # overrides original ModelGenerator#create_model_file to make a job_model instead of a model
9
+ # since we are inheriting from ModelGenerator, we get the tests and all the other good stuff
10
+ def create_model_file
11
+ template 'job_model.rb', File.join('app/models', class_path, "#{file_name}.rb")
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ module ActiveRecord::OrmHelpers
2
+ private
3
+ def migration_template(source, destination, config = {})
4
+ super 'migration.rb', destination, config
5
+ end
6
+ end
@@ -0,0 +1,17 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %> < <%= parent_class_name.classify %>
3
+ include OscMacheteRails::Statusable
4
+
5
+ <% attributes.select(&:reference?).each do |attribute| -%>
6
+ belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %>
7
+ <% end -%>
8
+ <% if attributes.any?(&:password_digest?) -%>
9
+ has_secure_password
10
+ <% end -%>
11
+
12
+ # Determine if the results are valid
13
+ # def results_valid?
14
+ # # CODE GOES HERE
15
+ # end
16
+ end
17
+ <% end -%>
@@ -0,0 +1,19 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration
2
+ def change
3
+ create_table :<%= table_name %> do |t|
4
+ <% attributes.each do |attribute| -%>
5
+ <% if attribute.password_digest? -%>
6
+ t.string :password_digest<%= attribute.inject_options %>
7
+ <% else -%>
8
+ t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
9
+ <% end -%>
10
+ <% end -%>
11
+ <% if options[:timestamps] %>
12
+ t.timestamps
13
+ <% end -%>
14
+ end
15
+ <% attributes_with_index.each do |attribute| -%>
16
+ add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
17
+ <% end -%>
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ <% module_namespacing do -%>
2
+ module <%= class_path.map(&:camelize).join('::') %>
3
+ def self.table_name_prefix
4
+ '<%= namespaced? ? namespaced_class_path.join('_') : class_path.join('_') %>_'
5
+ end
6
+ end
7
+ <% end -%>
@@ -0,0 +1,34 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %> < <%= parent_class_name.classify %>
3
+ has_many :<%= job.plural_name %>, dependent: :destroy
4
+ has_machete_workflow_of :<%= job.plural_name %>
5
+
6
+ <% attributes.select(&:reference?).each do |attribute| -%>
7
+ belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %>
8
+ <% end -%>
9
+ <% if attributes.any?(&:password_digest?) -%>
10
+ has_secure_password
11
+ <% end -%>
12
+
13
+ # Name that defines the template/target dirs
14
+ def staging_template_name
15
+ "<%= file_name %>"
16
+ end
17
+
18
+ # Define tasks to do after staging template directory typically copy over
19
+ # uploaded files here
20
+ # def after_stage(staged_dir)
21
+ # # CODE HERE
22
+ # end
23
+
24
+ # Build an array of Machete jobs that are then submitted to the batch server
25
+ def build_jobs(staged_dir, job_list = [])
26
+ job_list << OSC::Machete::Job.new(script: staged_dir.join("main.sh"))
27
+ end
28
+
29
+ # Make copy of workflow
30
+ def copy
31
+ self.dup
32
+ end
33
+ end
34
+ <% end -%>
@@ -0,0 +1,30 @@
1
+ require 'rails/generators/active_record/model/model_generator'
2
+ require 'generators/active_record/orm_helpers'
3
+ require 'generators/osc_machete_rails/job_helpers'
4
+
5
+ class ActiveRecord::WorkflowModelGenerator < ActiveRecord::Generators::ModelGenerator
6
+ include ActiveRecord::OrmHelpers
7
+ include OscMacheteRails::JobHelpers
8
+ source_root File.expand_path('../templates', __FILE__)
9
+
10
+ # add a new attribute to the generator
11
+ # the workflow needs to know what the job model is
12
+ # to render the template properly
13
+ attr_reader :job
14
+
15
+ # jobs is a new attribute type, like "references", so we can let the user specify the corresponding
16
+ # job model. This attribute is used in the workflow_model.rb template file. i.e.
17
+ #
18
+ # rails g osc_machete_rails:workflow_model Container name:string container_job:jobs
19
+ #
20
+ def initialize(args, *options)
21
+ @job = parse_job!(args)
22
+ super
23
+ end
24
+
25
+ # overrides original ModelGenerator#create_model_file to make a workflow_model instead of a model
26
+ # since we are inheriting from ModelGenerator, we get the tests and all the other good stuff
27
+ def create_model_file
28
+ template 'workflow_model.rb', File.join('app/models', class_path, "#{file_name}.rb")
29
+ end
30
+ end
@@ -0,0 +1,36 @@
1
+ Description:
2
+ Scaffolds an entire workflow, from models and migrations to controller and
3
+ views, along with a full test suite. The resource is ready to use as a
4
+ starting point for your Workflow.
5
+
6
+ Pass the name of the workflow (in singular form), either CamelCased or
7
+ under_scored, as the first argument, and an optional list of attribute
8
+ pairs.
9
+
10
+ Attributes are field arguments specifying the model's attributes. You can
11
+ optionally pass the type and an index to each field. For instance:
12
+ "title body:text tracking_id:integer:uniq" will generate a title field of
13
+ string type, a body with text type and a tracking_id as an integer with an
14
+ unique index. "index" could also be given instead of "uniq" if one desires
15
+ a non unique index.
16
+
17
+ Timestamps are added by default, so you don't have to specify them by hand
18
+ as 'created_at:datetime updated_at:datetime'.
19
+
20
+ You don't have to think up every attribute up front, but it helps to
21
+ sketch out a few so you can start working with the resource immediately.
22
+
23
+ For example, 'osc_machete_rails:scaffold container name pressure:decimal'
24
+ gives you a workflow model with those two attributes, a workflow template,
25
+ a job model, a controller that handles the
26
+ create/show/update/destroy/submit/copy, forms to create and edit your
27
+ posts, and an index that lists them all, as well as a resources :containers
28
+ declaration in config/routes.rb.
29
+
30
+ If you want to remove all the generated files, run
31
+ 'rails destroy osc_machete_rails:scaffold WorkflowName'.
32
+
33
+ Examples:
34
+ `rails generate osc_machete_rails:scaffold structure`
35
+ `rails generate osc_machete_rails:scaffold fan name comments:text centrifugal:boolean`
36
+ `rails generate osc_machete_rails:scaffold heatsink material temperature:decimal`
@@ -0,0 +1,5 @@
1
+ require 'rails/generators/erb/scaffold/scaffold_generator'
2
+
3
+ class OscMacheteRails::ErbGenerator < Erb::Generators::ScaffoldGenerator
4
+ source_root File.expand_path('../templates', __FILE__)
5
+ end
@@ -0,0 +1,21 @@
1
+ <%%# Uses rails_bootstrap_form gem. API at: https://github.com/bootstrap-ruby/rails-bootstrap-forms %>
2
+ <%%= bootstrap_form_for(<%= singular_table_name %>) do |f| %>
3
+ <%%= f.alert_message "Please fix the errors below." %>
4
+
5
+ <% attributes.each do |attribute| -%>
6
+ <% if attribute.password_digest? -%>
7
+ <%%= f.password_field :password %>
8
+ <%%= f.password_field :password_confirmation %>
9
+ <% else -%>
10
+ <%%= f.<%= attribute.field_type %> :<%= attribute.column_name %> %>
11
+ <% end -%>
12
+ <% end -%>
13
+
14
+ <%%= f.submit 'Save', class: 'btn btn-primary' %>
15
+ <%%= f.button 'Reset', type: :reset, class: 'btn btn-default' %>
16
+
17
+ <hr>
18
+
19
+ <%%= link_to 'Back', <%= index_helper %>_path, class: 'btn btn-default' %>
20
+ <%%= link_to 'Show', <%= singular_table_name %>, class: 'btn btn-primary' unless <%= singular_table_name %>.new_record? %>
21
+ <%% end %>
@@ -0,0 +1,5 @@
1
+ <div class="page-header">
2
+ <h2>Editing <%= singular_table_name.titleize %></h2>
3
+ </div>
4
+
5
+ <%%= render 'form', <%= singular_table_name %>: @<%= singular_table_name %> %>
@@ -0,0 +1,41 @@
1
+ <div class="page-header">
2
+ <h2>Listing <%= plural_table_name.titleize %></h2>
3
+ </div>
4
+
5
+ <table class="table data-table">
6
+ <thead>
7
+ <tr>
8
+ <th>#</th>
9
+ <th>Status</th>
10
+ <% attributes.reject(&:password_digest?).each do |attribute| -%>
11
+ <th><%= attribute.human_name %></th>
12
+ <% end -%>
13
+ <th class="no-sort"></th>
14
+ <th class="no-sort"></th>
15
+ <th class="no-sort"></th>
16
+ <th class="no-sort"></th>
17
+ <th class="no-sort"></th>
18
+ </tr>
19
+ </thead>
20
+
21
+ <tbody>
22
+ <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
23
+ <tr>
24
+ <td><%%= <%= singular_table_name %>.id %></td>
25
+ <td><%%= status_label(<%= singular_table_name %>) %></td>
26
+ <% attributes.reject(&:password_digest?).each do |attribute| -%>
27
+ <td><%%= <%= singular_table_name %>.<%= attribute.name %> %></td>
28
+ <% end -%>
29
+ <td><%%= link_to 'Submit', submit_<%= singular_table_name %>_path(<%= singular_table_name %>), method: :put, class: 'btn btn-success btn-sm' unless <%= singular_table_name %>.submitted? %></td>
30
+ <td><%%= link_to 'Show', <%= singular_table_name %>, class: 'btn btn-primary btn-sm' %></td>
31
+ <td><%%= link_to 'Edit', edit_<%= singular_table_name %>_path(<%= singular_table_name %>), class: 'btn btn-default btn-sm' unless <%= singular_table_name %>.submitted? %></td>
32
+ <td><%%= link_to 'Copy', copy_<%= singular_table_name %>_path(<%= singular_table_name %>), method: :put, class: 'btn btn-default btn-sm' %></td>
33
+ <td><%%= link_to 'Destroy', <%= singular_table_name %>, method: :delete, class: 'btn btn-danger btn-sm', data: { confirm: 'Are you sure?' } %></td>
34
+ </tr>
35
+ <%% end %>
36
+ </tbody>
37
+ </table>
38
+
39
+ <br>
40
+
41
+ <%%= link_to 'New <%= singular_table_name.titleize %>', new_<%= singular_table_name %>_path %>
@@ -0,0 +1,5 @@
1
+ <div class="page-header">
2
+ <h2>New <%= singular_table_name.titleize %></h2>
3
+ </div>
4
+
5
+ <%%= render 'form', <%= singular_table_name %>: @<%= singular_table_name %> %>
@@ -0,0 +1,13 @@
1
+ <div class="page-header">
2
+ <h2>Showing <%= singular_table_name.titleize %></h2>
3
+ </div>
4
+
5
+ <% attributes.reject(&:password_digest?).each do |attribute| -%>
6
+ <p>
7
+ <strong><%= attribute.human_name %>:</strong>
8
+ <%%= @<%= singular_table_name %>.<%= attribute.name %> %>
9
+ </p>
10
+
11
+ <% end -%>
12
+ <%%= link_to 'Back', <%= index_helper %>_path, class: 'btn btn-default' %>
13
+ <%%= link_to 'Edit', edit_<%= singular_table_name %>_path(@<%= singular_table_name %>), class: 'btn btn-default' %>
@@ -0,0 +1,10 @@
1
+ module OscMacheteRails::JobHelpers
2
+ private
3
+ def parse_job!(args)
4
+ jobs = args.grep(/:jobs$/)
5
+ args = args - jobs
6
+
7
+ job_attrib = jobs.first || "#{args.first.underscore}_job:jobs"
8
+ Rails::Generators::GeneratedAttribute.parse job_attrib
9
+ end
10
+ end
@@ -0,0 +1,28 @@
1
+ Description:
2
+ Stubs out a new job model. Pass the model name, either CamelCased or
3
+ under_scored, and an optional list of attribute pairs as arguments.
4
+
5
+ Attribute pairs are field:type arguments specifying the
6
+ model's attributes. Timestamps are added by default, so you don't have to
7
+ specify them by hand as 'created_at:datetime updated_at:datetime'.
8
+
9
+ You don't have to think up every attribute up front, but it helps to
10
+ sketch out a few so you can start working with the model immediately.
11
+
12
+ This generator invokes your configured ORM and test framework, which
13
+ defaults to ActiveRecord and TestUnit.
14
+
15
+ Available field types:
16
+
17
+ For more information see:
18
+
19
+ `rails generate model --help`
20
+
21
+ Example:
22
+ `rails generate osc_machete_rails:job_model ThingJob thing:references`
23
+
24
+ For ActiveRecord and TestUnit it creates:
25
+ Model: app/models/thing_job.rb
26
+ Test: test/models/thing_job_test.rb
27
+ Fixtures: test/fixtures/thing_jobs.yml
28
+ Migration: db/migrate/XXX_create_thing_jobs.rb
@@ -0,0 +1,13 @@
1
+ class OscMacheteRails::JobModelGenerator < Rails::Generators::NamedBase
2
+ source_root File.expand_path("../templates", __FILE__)
3
+
4
+ def initialize(args, *options)
5
+ args |= %w(status:string)
6
+ args |= %w(job_cache:text)
7
+
8
+ super
9
+ end
10
+
11
+ argument :attributes, type: :array, default: [], banner: "field[:type][:index] field[:type][:index]"
12
+ hook_for :orm, required: true
13
+ end
@@ -0,0 +1,3 @@
1
+ Description:
2
+ Create rails files for resource_route generator. Adds two Workflow specific
3
+ routes.
@@ -0,0 +1,57 @@
1
+ class OscMacheteRails::ResourceRouteGenerator < Rails::Generators::NamedBase
2
+ source_root File.expand_path('../templates', __FILE__)
3
+
4
+ # Properly nests namespaces passed into a generator
5
+ #
6
+ # $ rails generate osc_machete_rails:workflow_route admin/users/products
7
+ #
8
+ # should give you
9
+ #
10
+ # namespace :admin do
11
+ # namespace :users
12
+ # resources :products do
13
+ # member do
14
+ # put 'submit'
15
+ # put 'copy'
16
+ # end
17
+ # end
18
+ # end
19
+ # end
20
+ def add_workflow_route
21
+ return if options[:actions].present?
22
+
23
+ # iterates over all namespaces and opens up blocks
24
+ regular_class_path.each_with_index do |namespace, index|
25
+ write("namespace :#{namespace} do", index + 1)
26
+ end
27
+
28
+ # inserts the primary resource
29
+ write("resources :#{file_name.pluralize} do", route_length + 1)
30
+ write("member do", route_length + 2)
31
+ write("put 'submit'", route_length + 3)
32
+ write("put 'copy'", route_length + 3)
33
+ write("end", route_length + 2)
34
+ write("end", route_length + 1)
35
+
36
+ # ends blocks
37
+ regular_class_path.each_index do |index|
38
+ write("end", route_length - index)
39
+ end
40
+
41
+ # route prepends two spaces onto the front of the string that is passed, this corrects that
42
+ route route_string[2..-1]
43
+ end
44
+
45
+ private
46
+ def route_string
47
+ @route_string ||= ""
48
+ end
49
+
50
+ def write(str, indent)
51
+ route_string << "#{" " * indent}#{str}\n"
52
+ end
53
+
54
+ def route_length
55
+ regular_class_path.length
56
+ end
57
+ end
@@ -0,0 +1,17 @@
1
+ Description:
2
+ Stubs out a scaffolded controller, its seven RESTful actions + two Workflow
3
+ actions and related views. Pass the model name, either CamelCased or
4
+ under_scored. The controller name is retrieved as a pluralized version of
5
+ the model name.
6
+
7
+ This generates a controller class in app/controllers and invokes helper,
8
+ template engine and test framework generators.
9
+
10
+ Example:
11
+ `rails generate osc_machete_rails:scaffold_controller Thing`
12
+
13
+ Thing controller with URLs like /thing/submit.
14
+ Controller: app/controllers/things_controller.rb
15
+ Test: test/controllers/things_controller_test.rb
16
+ Views: app/views/things/index.html.erb [...]
17
+ Helper: app/helpers/things_helper.rb
@@ -0,0 +1,24 @@
1
+ require 'rails/generators/rails/scaffold_controller/scaffold_controller_generator'
2
+ require 'generators/osc_machete_rails/job_helpers'
3
+
4
+ class OscMacheteRails::ScaffoldControllerGenerator < Rails::Generators::ScaffoldControllerGenerator
5
+ include OscMacheteRails::JobHelpers
6
+ source_root File.expand_path('../templates', __FILE__)
7
+
8
+ # attribute to know what the job model is - see comments on active_record/workflow_model_generator.rb
9
+ attr_reader :job
10
+
11
+ def initialize(args, *options)
12
+ @job = parse_job!(args)
13
+
14
+ super
15
+ end
16
+
17
+ # override ScaffoldControllerGenerator
18
+ # by recalling hook_for, the erb_generator will be searched for under OscMacheteRails
19
+ # (idiosyncracy of Thor)
20
+ #
21
+ # the default template engine is erb, so we provide specific erb_generator.rb and its templates
22
+ # see lib/generators/osc_machete_rails/erb for details
23
+ hook_for :template_engine
24
+ end