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
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