stonepath 0.1.2 → 0.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.
- data/VERSION +1 -1
- data/lib/stonepath.rb +2 -3
- data/lib/stonepath/extensions/action_view.rb +1 -1
- data/lib/stonepath/extensions/rails_generator_commands.rb +42 -0
- data/rails_generators/{stonepath → stonepath_event_log}/stonepath_event_log_generator.rb +0 -0
- data/rails_generators/{stonepath → stonepath_event_log}/templates/create_event_records.rb +0 -0
- data/rails_generators/{stonepath → stonepath_event_log}/templates/event_record.rb +0 -0
- data/rails_generators/stonepath_task/USAGE +1 -0
- data/rails_generators/stonepath_task/stonepath_task_generator.rb +29 -0
- data/rails_generators/stonepath_task/templates/generic_task.rb +23 -0
- data/rails_generators/stonepath_task/templates/generic_task_migration.rb +36 -0
- data/rails_generators/stonepath_workitem/USAGE +51 -0
- data/rails_generators/stonepath_workitem/stonepath_workitem_generator.rb +196 -0
- data/rails_generators/stonepath_workitem/templates/actions/create.rb +9 -0
- data/rails_generators/stonepath_workitem/templates/actions/destroy.rb +6 -0
- data/rails_generators/stonepath_workitem/templates/actions/edit.rb +3 -0
- data/rails_generators/stonepath_workitem/templates/actions/index.rb +3 -0
- data/rails_generators/stonepath_workitem/templates/actions/new.rb +3 -0
- data/rails_generators/stonepath_workitem/templates/actions/show.rb +3 -0
- data/rails_generators/stonepath_workitem/templates/actions/update.rb +9 -0
- data/rails_generators/stonepath_workitem/templates/controller.rb +3 -0
- data/rails_generators/stonepath_workitem/templates/event_controller.rb +25 -0
- data/rails_generators/stonepath_workitem/templates/fixtures.yml +9 -0
- data/rails_generators/stonepath_workitem/templates/helper.rb +2 -0
- data/rails_generators/stonepath_workitem/templates/migration.rb +24 -0
- data/rails_generators/stonepath_workitem/templates/model.rb +33 -0
- data/rails_generators/stonepath_workitem/templates/tests/testunit/actions/create.rb +11 -0
- data/rails_generators/stonepath_workitem/templates/tests/testunit/actions/destroy.rb +6 -0
- data/rails_generators/stonepath_workitem/templates/tests/testunit/actions/edit.rb +4 -0
- data/rails_generators/stonepath_workitem/templates/tests/testunit/actions/index.rb +4 -0
- data/rails_generators/stonepath_workitem/templates/tests/testunit/actions/new.rb +4 -0
- data/rails_generators/stonepath_workitem/templates/tests/testunit/actions/show.rb +4 -0
- data/rails_generators/stonepath_workitem/templates/tests/testunit/actions/update.rb +11 -0
- data/rails_generators/stonepath_workitem/templates/tests/testunit/controller.rb +5 -0
- data/rails_generators/stonepath_workitem/templates/tests/testunit/model.rb +7 -0
- data/rails_generators/stonepath_workitem/templates/views/erb/_form.html.erb +10 -0
- data/rails_generators/stonepath_workitem/templates/views/erb/edit.html.erb +12 -0
- data/rails_generators/stonepath_workitem/templates/views/erb/index.html.erb +27 -0
- data/rails_generators/stonepath_workitem/templates/views/erb/new.html.erb +5 -0
- data/rails_generators/stonepath_workitem/templates/views/erb/show.html.erb +26 -0
- metadata +39 -12
- data/lib/stonepath/extensions/action_controller.rb +0 -50
- data/lib/stonepath/extensions/kernel.rb +0 -5
- data/rails_generators/stonepath/stonepath_task_generator.rb +0 -9
- data/rails_generators/stonepath/stonepath_workitem_generator.rb +0 -8
- data/rails_generators/stonepath/templates/generic_task.rb +0 -8
- data/rails_generators/stonepath/templates/generic_task_migration.rb +0 -20
- data/rails_generators/stonepath/templates/workitem_readme.txt +0 -14
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.2.0
|
data/lib/stonepath.rb
CHANGED
|
@@ -7,9 +7,10 @@ module StonePath
|
|
|
7
7
|
|
|
8
8
|
base.instance_eval {
|
|
9
9
|
|
|
10
|
-
def stonepath_workitem
|
|
10
|
+
def stonepath_workitem(&config_block)
|
|
11
11
|
require File.expand_path(File.dirname(__FILE__)) + "/stonepath/work_item.rb"
|
|
12
12
|
include StonePath::WorkItem
|
|
13
|
+
instance_eval &config_block if config_block
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
def stonepath_task(&config_block)
|
|
@@ -51,8 +52,6 @@ require "stonepath/config"
|
|
|
51
52
|
# init.rb chokes on load. I suspect this is an artificial issue because of the way the
|
|
52
53
|
# embedded test app works.
|
|
53
54
|
load File.expand_path( File.dirname(__FILE__)) + "/stonepath/extensions/activerecordbase.rb"
|
|
54
|
-
load File.expand_path( File.dirname(__FILE__)) + "/stonepath/extensions/action_controller.rb"
|
|
55
|
-
load File.expand_path( File.dirname(__FILE__)) + "/stonepath/extensions/kernel.rb"
|
|
56
55
|
load File.expand_path( File.dirname(__FILE__)) + '/stonepath/extensions/action_view.rb'
|
|
57
56
|
|
|
58
57
|
|
|
@@ -6,7 +6,7 @@ if Object.const_defined?(:ActionView)
|
|
|
6
6
|
module UrlHelper
|
|
7
7
|
|
|
8
8
|
def link_to_stonepath_event(object, event)
|
|
9
|
-
path_method = object.class.to_s.
|
|
9
|
+
path_method = object.class.to_s.tableize.singularize + "_event_path"
|
|
10
10
|
path = self.send(path_method, object, :id => event.to_s)
|
|
11
11
|
link_to(event.to_s.humanize, path, :method => :post)
|
|
12
12
|
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
module Rails
|
|
2
|
+
module Generator
|
|
3
|
+
module Commands
|
|
4
|
+
|
|
5
|
+
Create.class_eval {
|
|
6
|
+
def route_stonepath_workitems(resource)
|
|
7
|
+
sentinel = 'ActionController::Routing::Routes.draw do |map|'
|
|
8
|
+
logger.route "map.stonepath_workitems #{resource}"
|
|
9
|
+
unless options[:pretend]
|
|
10
|
+
gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/mi do |match|
|
|
11
|
+
"#{match}
|
|
12
|
+
|
|
13
|
+
map.resources :#{resource} do |o|
|
|
14
|
+
o.resource :event, {:only => \"create\", :controller => \"#{resource.singularize}_events\"}
|
|
15
|
+
end
|
|
16
|
+
"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
Destroy.class_eval {
|
|
24
|
+
def route_stonepath_workitems(*resources)
|
|
25
|
+
resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
|
|
26
|
+
look_for = "\n map.stonepath_workitems #{resource_list}\n"
|
|
27
|
+
logger.route "map.stonepath_workitems #{resource_list}"
|
|
28
|
+
gsub_file 'config/routes.rb', /(#{look_for})/mi, ''
|
|
29
|
+
end
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
List.class_eval {
|
|
34
|
+
def route_stonepath_workitems(*resources)
|
|
35
|
+
resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
|
|
36
|
+
logger.route "map.stonepath_workitems #{resource_list}"
|
|
37
|
+
end
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Usage goes here.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
class StonepathTaskGenerator < Rails::Generator::Base
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
attr_accessor :name, :attributes
|
|
5
|
+
|
|
6
|
+
def initialize(runtime_args, runtime_options = {})
|
|
7
|
+
super
|
|
8
|
+
usage if @args.empty?
|
|
9
|
+
|
|
10
|
+
@name = @args.first
|
|
11
|
+
@controller_actions = []
|
|
12
|
+
@attributes = []
|
|
13
|
+
|
|
14
|
+
@args[1..-1].each do |arg|
|
|
15
|
+
if arg.include? ':'
|
|
16
|
+
@attributes << Rails::Generator::GeneratedAttribute.new(*arg.split(":"))
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
@attributes.uniq!
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def manifest
|
|
24
|
+
record do |m|
|
|
25
|
+
m.template('generic_task.rb', "app/models/#{@name.tableize.singularize}.rb")
|
|
26
|
+
m.migration_template("generic_task_migration.rb", "db/migrate", :migration_file_name => "create_#{@name.tableize}")
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class <%= args[0].classify %> < ActiveRecord::Base
|
|
2
|
+
include StonePath
|
|
3
|
+
|
|
4
|
+
stonepath_task
|
|
5
|
+
|
|
6
|
+
#logs_transitions # uncomment this if you generate the event log.
|
|
7
|
+
|
|
8
|
+
attr_accessible <%= attributes.map { |a| ":#{a.name}" }.join(", ") %>
|
|
9
|
+
|
|
10
|
+
# you might think 'overdue' should be a state, but no, part of the stonepath
|
|
11
|
+
# methodology is that states should be as free of time definition as possible.
|
|
12
|
+
# Thinking about it, this should make sense. Think of the conversation:
|
|
13
|
+
# A: "That isn't done yet?"
|
|
14
|
+
# B: "No, it's overdue"
|
|
15
|
+
# A: "Well, where is it then?"
|
|
16
|
+
# B: "It's still on Mike's desk, in process".
|
|
17
|
+
#
|
|
18
|
+
# so the state would be 'in process', even though it is 'overdue'.
|
|
19
|
+
def overdue?
|
|
20
|
+
(Time.now > due_at) && !self.completed?
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
class Create<%= args[0].tableize.classify.pluralize %> < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
create_table :<%= args[0].tableize %> do |t|
|
|
4
|
+
|
|
5
|
+
# don't change these unless you want to get deep into meta in the
|
|
6
|
+
# stonepath gem.
|
|
7
|
+
t.string :aasm_state
|
|
8
|
+
t.references :workitem, :polymorphic => true
|
|
9
|
+
t.references :workbench, :polymorphic => true
|
|
10
|
+
|
|
11
|
+
t.datetime :due_at
|
|
12
|
+
t.datetime :completed_at
|
|
13
|
+
t.timestamps
|
|
14
|
+
|
|
15
|
+
# This "urgent at' concept was useful in one of the domains StonePath
|
|
16
|
+
# was written/extracted from. The idea is thatm while something is 'due'
|
|
17
|
+
# at a specific time, it might become urgent shortly before it is due.
|
|
18
|
+
# In that domain, we color-coded tasks as green (due date is far out)
|
|
19
|
+
# yellow (urgent timestap has passed), and red (overdue - due date
|
|
20
|
+
# has passed). This won't become part of the framework, but I like the
|
|
21
|
+
# idea so much I thought I'd comment it here until it gets in some
|
|
22
|
+
# official documentation for 'advanced usage'.
|
|
23
|
+
# t.datetime :urgent_at
|
|
24
|
+
|
|
25
|
+
# Your attributes should be defined here.
|
|
26
|
+
<%- for attribute in attributes -%>
|
|
27
|
+
t.<%= attribute.type %> :<%= attribute.name %>
|
|
28
|
+
<%- end -%>
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.down
|
|
34
|
+
drop_table :<%= args[0].tableize %>
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
Description:
|
|
2
|
+
Scaffolds an entire resource, from model and migration to controller and
|
|
3
|
+
views. The resource is ready to use as a starting point for your restful,
|
|
4
|
+
resource-oriented application. Tests or specs are also generated depending
|
|
5
|
+
on if you have a "spec" directory or not.
|
|
6
|
+
|
|
7
|
+
IMPORTANT: This generator uses the "title" helper method which is generated
|
|
8
|
+
by the nifty_layout generator. You may want to run that generator first.
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
Pass the name of the model, either CamelCased or under_scored, as the first
|
|
12
|
+
argument, and an optional list of attribute pairs and controller actions.
|
|
13
|
+
|
|
14
|
+
If no controller actions are specified, they will default to index, show,
|
|
15
|
+
new, create, edit, update, and destroy.
|
|
16
|
+
|
|
17
|
+
IMPORTANT: If no attribute pairs are specified, no model will be generated.
|
|
18
|
+
It will try to determine the attributes from an existing model.
|
|
19
|
+
|
|
20
|
+
Attribute pairs are column_name:sql_type arguments specifying the
|
|
21
|
+
model's attributes. Timestamps are added by default, so you don't have to
|
|
22
|
+
specify them by hand as 'created_at:datetime updated_at:datetime'.
|
|
23
|
+
|
|
24
|
+
For example, `nifty_scaffold post name:string content:text hidden:boolean`
|
|
25
|
+
gives you a model with those three attributes, a controller that handles
|
|
26
|
+
the create/show/update/destroy, forms to create and edit your posts, and
|
|
27
|
+
an index that lists them all, as well as a map.resources :posts
|
|
28
|
+
declaration in config/routes.rb.
|
|
29
|
+
|
|
30
|
+
Adding an "!" in the mix of arguments will invert the passed controller
|
|
31
|
+
actions. This will include all 7 controller actitons except the ones
|
|
32
|
+
mentioned. This option doesn't effect model attributes.
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
script/generate nifty_scaffold post
|
|
36
|
+
|
|
37
|
+
Will create a controller called "posts" it will contain all seven
|
|
38
|
+
CRUD actions along with the views. A model will NOT be created,
|
|
39
|
+
instead it will look for an existing model and use those attributes.
|
|
40
|
+
|
|
41
|
+
script/generate nifty_scaffold post name:string content:text index new edit
|
|
42
|
+
|
|
43
|
+
Will create a Post model and migration file with the name and content
|
|
44
|
+
attributes. It will also create a controller with index, new, create,
|
|
45
|
+
edit, and update actions. Notice the create and update actions are
|
|
46
|
+
added automatically with new and edit.
|
|
47
|
+
|
|
48
|
+
script/generate nifty_scaffold post ! show new
|
|
49
|
+
|
|
50
|
+
Creates a posts controller (no model) with index, edit, update, and
|
|
51
|
+
destroy actions.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
class StonepathWorkitemGenerator < Rails::Generator::Base
|
|
2
|
+
|
|
3
|
+
load File.expand_path( File.dirname(__FILE__)) + '/../../lib/stonepath/extensions/rails_generator_commands.rb'
|
|
4
|
+
|
|
5
|
+
attr_accessor :name, :attributes
|
|
6
|
+
|
|
7
|
+
def initialize(runtime_args, runtime_options = {})
|
|
8
|
+
super
|
|
9
|
+
usage if @args.empty?
|
|
10
|
+
|
|
11
|
+
@name = @args.first
|
|
12
|
+
@attributes = []
|
|
13
|
+
@args[1..-1].each do |arg|
|
|
14
|
+
if arg.include? ':'
|
|
15
|
+
@attributes << Rails::Generator::GeneratedAttribute.new(*arg.split(":"))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
@attributes.uniq!
|
|
19
|
+
@controller_actions = all_actions
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def manifest
|
|
23
|
+
record do |m|
|
|
24
|
+
|
|
25
|
+
m.directory "app/models"
|
|
26
|
+
m.template "model.rb", "app/models/#{singular_name}.rb"
|
|
27
|
+
m.migration_template "migration.rb", "db/migrate", :migration_file_name => "create_#{plural_name}"
|
|
28
|
+
m.directory "test/unit"
|
|
29
|
+
m.template "tests/#{test_framework}/model.rb", "test/unit/#{singular_name}_test.rb"
|
|
30
|
+
m.directory "test/fixtures"
|
|
31
|
+
m.template "fixtures.yml", "test/fixtures/#{plural_name}.yml"
|
|
32
|
+
|
|
33
|
+
m.directory "app/controllers"
|
|
34
|
+
m.template "controller.rb", "app/controllers/#{plural_name}_controller.rb"
|
|
35
|
+
m.template "event_controller.rb", "app/controllers/#{singular_name}_events_controller.rb"
|
|
36
|
+
|
|
37
|
+
m.directory "app/helpers"
|
|
38
|
+
m.template "helper.rb", "app/helpers/#{plural_name}_helper.rb"
|
|
39
|
+
|
|
40
|
+
m.directory "app/views/#{plural_name}"
|
|
41
|
+
@controller_actions.each do |action|
|
|
42
|
+
if File.exist? source_path("views/#{view_language}/#{action}.html.#{view_language}")
|
|
43
|
+
m.template "views/#{view_language}/#{action}.html.#{view_language}", "app/views/#{plural_name}/#{action}.html.#{view_language}"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if form_partial?
|
|
48
|
+
m.template "views/#{view_language}/_form.html.#{view_language}", "app/views/#{plural_name}/_form.html.#{view_language}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
m.route_stonepath_workitems plural_name
|
|
52
|
+
|
|
53
|
+
m.directory "test/functional"
|
|
54
|
+
m.template "tests/#{test_framework}/controller.rb", "test/functional/#{plural_name}_controller_test.rb"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def form_partial?
|
|
59
|
+
actions? :new, :edit
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def all_actions
|
|
63
|
+
%w[index show new create edit update destroy]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def action?(name)
|
|
67
|
+
@controller_actions.include? name.to_s
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def actions?(*names)
|
|
71
|
+
names.all? { |n| action? n.to_s }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def singular_name
|
|
75
|
+
name.underscore
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def plural_name
|
|
79
|
+
name.underscore.pluralize
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def class_name
|
|
83
|
+
name.camelize
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def object_id_name
|
|
87
|
+
(class_name.tableize.singularize + "_id")
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def plural_class_name
|
|
91
|
+
plural_name.camelize
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def controller_methods(dir_name)
|
|
95
|
+
@controller_actions.map do |action|
|
|
96
|
+
read_template("#{dir_name}/#{action}.rb")
|
|
97
|
+
end.join(" \n").strip
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def render_form
|
|
101
|
+
if form_partial?
|
|
102
|
+
if options[:haml]
|
|
103
|
+
"= render :partial => 'form'"
|
|
104
|
+
else
|
|
105
|
+
"<%= render :partial => 'form' %>"
|
|
106
|
+
end
|
|
107
|
+
else
|
|
108
|
+
read_template("views/#{view_language}/_form.html.#{view_language}")
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def items_path(suffix = 'path')
|
|
113
|
+
if action? :index
|
|
114
|
+
"#{plural_name}_#{suffix}"
|
|
115
|
+
else
|
|
116
|
+
"root_#{suffix}"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def item_path(suffix = 'path')
|
|
121
|
+
if action? :show
|
|
122
|
+
"@#{singular_name}"
|
|
123
|
+
else
|
|
124
|
+
items_path(suffix)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def item_path_for_spec(suffix = 'path')
|
|
129
|
+
if action? :show
|
|
130
|
+
"#{singular_name}_#{suffix}(assigns[:#{singular_name}])"
|
|
131
|
+
else
|
|
132
|
+
items_path(suffix)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def item_path_for_test(suffix = 'path')
|
|
137
|
+
if action? :show
|
|
138
|
+
"#{singular_name}_#{suffix}(assigns(:#{singular_name}))"
|
|
139
|
+
else
|
|
140
|
+
items_path(suffix)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def model_columns_for_attributes
|
|
145
|
+
class_name.constantize.columns.reject do |column|
|
|
146
|
+
column.name.to_s =~ /^(id|created_at|updated_at)$/
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def rspec?
|
|
151
|
+
test_framework == :rspec
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
protected
|
|
155
|
+
|
|
156
|
+
def view_language
|
|
157
|
+
options[:haml] ? 'haml' : 'erb'
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def test_framework
|
|
161
|
+
options[:test_framework] ||= default_test_framework
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def default_test_framework
|
|
165
|
+
File.exist?(destination_path("spec")) ? :rspec : :testunit
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def add_options!(opt)
|
|
169
|
+
opt.separator ''
|
|
170
|
+
opt.separator 'Options:'
|
|
171
|
+
# opt.on("--skip-model", "Don't generate a model or migration file.") { |v| options[:skip_model] = v }
|
|
172
|
+
# opt.on("--skip-migration", "Don't generate migration file for model.") { |v| options[:skip_migration] = v }
|
|
173
|
+
# opt.on("--skip-timestamps", "Don't add timestamps to migration file.") { |v| options[:skip_timestamps] = v }
|
|
174
|
+
# opt.on("--skip-controller", "Don't generate controller, helper, or views.") { |v| options[:skip_controller] = v }
|
|
175
|
+
# opt.on("--invert", "Generate all controller actions except these mentioned.") { |v| options[:invert] = v }
|
|
176
|
+
# opt.on("--haml", "Generate HAML views instead of ERB.") { |v| options[:haml] = v }
|
|
177
|
+
# opt.on("--testunit", "Use test/unit for test files.") { options[:test_framework] = :testunit }
|
|
178
|
+
# opt.on("--rspec", "Use RSpec for test files.") { options[:test_framework] = :rspec }
|
|
179
|
+
# opt.on("--shoulda", "Use Shoulda for test files.") { options[:test_framework] = :shoulda }
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# is there a better way to do this? Perhaps with const_defined?
|
|
183
|
+
def model_exists?
|
|
184
|
+
File.exist? destination_path("app/models/#{singular_name}.rb")
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def read_template(relative_path)
|
|
188
|
+
ERB.new(File.read(source_path(relative_path)), nil, '-').result(binding)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def banner
|
|
192
|
+
<<-EOS
|
|
193
|
+
Creates a WorkItem as defined by the Stonepath Workflow Methodology
|
|
194
|
+
EOS
|
|
195
|
+
end
|
|
196
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
def create
|
|
2
|
+
@<%= singular_name %> = <%= class_name %>.new(params[:<%= singular_name %>])
|
|
3
|
+
if @<%= singular_name %>.save
|
|
4
|
+
flash[:notice] = "Successfully created <%= name.underscore.humanize.downcase %>."
|
|
5
|
+
redirect_to <%= item_path('url') %>
|
|
6
|
+
else
|
|
7
|
+
render :action => 'new'
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
def update
|
|
2
|
+
@<%= singular_name %> = <%= class_name %>.find(params[:id])
|
|
3
|
+
if @<%= singular_name %>.update_attributes(params[:<%= singular_name %>])
|
|
4
|
+
flash[:notice] = "Successfully updated <%= name.underscore.humanize.downcase %>."
|
|
5
|
+
redirect_to <%= item_path('url') %>
|
|
6
|
+
else
|
|
7
|
+
render :action => 'edit'
|
|
8
|
+
end
|
|
9
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# this is now your file to do with as you see fit. Before you modify it though, make sure you
|
|
2
|
+
# understand how the nested restful routes are defined in the routes.rb file!
|
|
3
|
+
|
|
4
|
+
class <%= class_name %>EventsController < ApplicationController
|
|
5
|
+
|
|
6
|
+
def create
|
|
7
|
+
if request.post?
|
|
8
|
+
@object = <%= class_name %>.find(params[:<%= object_id_name %>])
|
|
9
|
+
event = params[:id]
|
|
10
|
+
if <%= class_name %>.aasm_events.keys.include?(event.to_sym)
|
|
11
|
+
respond_to do |format|
|
|
12
|
+
if @object.send(event + "!")
|
|
13
|
+
flash[:notice] = "Event '#{event}' was successfully performed."
|
|
14
|
+
format.html { redirect_to(@object) }
|
|
15
|
+
format.xml { render :xml => @object }
|
|
16
|
+
else
|
|
17
|
+
flash[:notice] = "Event '#{event}' was NOT successfully performed."
|
|
18
|
+
format.html { redirect_to(@object) }
|
|
19
|
+
format.xml { render :xml => @object.errors, :status => :unprocessable_entity }
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
class Create<%= plural_class_name %> < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
create_table :<%= plural_name %> do |t|
|
|
4
|
+
# These are the attributes of a workitem
|
|
5
|
+
t.string :aasm_state
|
|
6
|
+
t.integer :owner_id
|
|
7
|
+
|
|
8
|
+
# Your attributes should be defined here.
|
|
9
|
+
<%- for attribute in attributes -%>
|
|
10
|
+
t.<%= attribute.type %> :<%= attribute.name %>
|
|
11
|
+
<%- end -%>
|
|
12
|
+
<%- unless options[:skip_timestamps] -%>
|
|
13
|
+
t.timestamps
|
|
14
|
+
<%- end -%>
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
#I'd like to create an index on aasm_state here.
|
|
18
|
+
# you might optionally want to index owner_id
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.down
|
|
22
|
+
drop_table :<%= plural_name %>
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
class <%= class_name %> < ActiveRecord::Base
|
|
2
|
+
include StonePath
|
|
3
|
+
|
|
4
|
+
stonepath_workitem do
|
|
5
|
+
#owned_by :your_owning class
|
|
6
|
+
|
|
7
|
+
#tasked_through :your_implementation_of_stonepath_task
|
|
8
|
+
|
|
9
|
+
# This is an example trivial workflow. This is now yours to change as
|
|
10
|
+
# you see fit.
|
|
11
|
+
aasm_initial_state :pending
|
|
12
|
+
|
|
13
|
+
aasm_state :pending
|
|
14
|
+
aasm_state :in_process
|
|
15
|
+
aasm_state :completed
|
|
16
|
+
|
|
17
|
+
aasm_event :activate do
|
|
18
|
+
transitions :to => :in_process, :from => :pending
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
aasm_event :complete do
|
|
22
|
+
transitions :to => :completed, :from => :in_process
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
aasm_event :reactivate do
|
|
26
|
+
transitions :to => :in_process, :from => :completed
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
attr_accessible <%= attributes.map { |a| ":#{a.name}" }.join(", ") %>
|
|
32
|
+
|
|
33
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
def test_create_invalid
|
|
2
|
+
<%= class_name %>.any_instance.stubs(:valid?).returns(false)
|
|
3
|
+
post :create
|
|
4
|
+
assert_template 'new'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def test_create_valid
|
|
8
|
+
<%= class_name %>.any_instance.stubs(:valid?).returns(true)
|
|
9
|
+
post :create
|
|
10
|
+
assert_redirected_to <%= item_path_for_test('url') %>
|
|
11
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
def test_update_invalid
|
|
2
|
+
<%= class_name %>.any_instance.stubs(:valid?).returns(false)
|
|
3
|
+
put :update, :id => <%= class_name %>.first
|
|
4
|
+
assert_template 'edit'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def test_update_valid
|
|
8
|
+
<%= class_name %>.any_instance.stubs(:valid?).returns(true)
|
|
9
|
+
put :update, :id => <%= class_name %>.first
|
|
10
|
+
assert_redirected_to <%= item_path_for_test('url') %>
|
|
11
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<%% form_for @<%= singular_name %> do |f| %>
|
|
2
|
+
<%%= f.error_messages %>
|
|
3
|
+
<%- for attribute in attributes -%>
|
|
4
|
+
<p>
|
|
5
|
+
<%%= f.label :<%= attribute.name %> %><br />
|
|
6
|
+
<%%= f.<%= attribute.field_type %> :<%= attribute.name %> %>
|
|
7
|
+
</p>
|
|
8
|
+
<%- end -%>
|
|
9
|
+
<p><%%= f.submit "Submit" %></p>
|
|
10
|
+
<%% end %>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<%= render_form %>
|
|
2
|
+
|
|
3
|
+
<%- if actions? :show, :index -%>
|
|
4
|
+
<p>
|
|
5
|
+
<%- if action? :show -%>
|
|
6
|
+
<%%= link_to "Show", @<%= singular_name %> %> |
|
|
7
|
+
<%- end -%>
|
|
8
|
+
<%- if action? :index -%>
|
|
9
|
+
<%%= link_to "View All", <%= plural_name %>_path %>
|
|
10
|
+
<%- end -%>
|
|
11
|
+
</p>
|
|
12
|
+
<%- end -%>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<table>
|
|
2
|
+
<tr>
|
|
3
|
+
<%- for attribute in attributes -%>
|
|
4
|
+
<th><%= attribute.column.human_name.titleize %></th>
|
|
5
|
+
<%- end -%>
|
|
6
|
+
</tr>
|
|
7
|
+
<%% for <%= singular_name %> in @<%= plural_name %> %>
|
|
8
|
+
<tr>
|
|
9
|
+
<%- for attribute in attributes -%>
|
|
10
|
+
<td><%%=h <%= singular_name %>.<%= attribute.name %> %></td>
|
|
11
|
+
<%- end -%>
|
|
12
|
+
<%- if action? :show -%>
|
|
13
|
+
<td><%%= link_to "Show", <%= singular_name %> %></td>
|
|
14
|
+
<%- end -%>
|
|
15
|
+
<%- if action? :edit -%>
|
|
16
|
+
<td><%%= link_to "Edit", edit_<%= singular_name %>_path(<%= singular_name %>) %></td>
|
|
17
|
+
<%- end -%>
|
|
18
|
+
<%- if action? :destroy -%>
|
|
19
|
+
<td><%%= link_to "Destroy", <%= singular_name %>, :confirm => 'Are you sure?', :method => :delete %></td>
|
|
20
|
+
<%- end -%>
|
|
21
|
+
</tr>
|
|
22
|
+
<%% end %>
|
|
23
|
+
</table>
|
|
24
|
+
|
|
25
|
+
<%- if action? :new -%>
|
|
26
|
+
<p><%%= link_to "New <%= singular_name.titleize %>", new_<%= singular_name %>_path %></p>
|
|
27
|
+
<%- end -%>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<%- for attribute in attributes -%>
|
|
2
|
+
<p>
|
|
3
|
+
<strong><%= attribute.column.human_name.titleize %>:</strong>
|
|
4
|
+
<%%=h @<%= singular_name %>.<%= attribute.name %> %>
|
|
5
|
+
</p>
|
|
6
|
+
<%- end -%>
|
|
7
|
+
|
|
8
|
+
<p>
|
|
9
|
+
<strong>Current state: </strong><%%= @<%= singular_name %>.aasm_state.humanize %>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
<p>
|
|
13
|
+
<%% @<%= singular_name %>.aasm_events_for_current_state.each do |event| %>
|
|
14
|
+
<%%= link_to_stonepath_event(@<%= singular_name %>, event) %> |
|
|
15
|
+
<%% end %>
|
|
16
|
+
|
|
17
|
+
<%- if action? :edit -%>
|
|
18
|
+
<%%= link_to "Edit", edit_<%= singular_name %>_path(@<%= singular_name %>) %> |
|
|
19
|
+
<%- end -%>
|
|
20
|
+
<%- if action? :destroy -%>
|
|
21
|
+
<%%= link_to "Destroy", @<%= singular_name %>, :confirm => 'Are you sure?', :method => :delete %> |
|
|
22
|
+
<%- end -%>
|
|
23
|
+
<%- if action? :index -%>
|
|
24
|
+
<%%= link_to "View All", <%= plural_name %>_path %>
|
|
25
|
+
<%- end -%>
|
|
26
|
+
</p>
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stonepath
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Bock
|
|
@@ -9,7 +9,7 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2010-01-
|
|
12
|
+
date: 2010-01-07 00:00:00 -05:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
@@ -45,10 +45,9 @@ files:
|
|
|
45
45
|
- lib/stonepath/config.rb
|
|
46
46
|
- lib/stonepath/controller_hooks.rb
|
|
47
47
|
- lib/stonepath/event_logging.rb
|
|
48
|
-
- lib/stonepath/extensions/action_controller.rb
|
|
49
48
|
- lib/stonepath/extensions/action_view.rb
|
|
50
49
|
- lib/stonepath/extensions/activerecordbase.rb
|
|
51
|
-
- lib/stonepath/extensions/
|
|
50
|
+
- lib/stonepath/extensions/rails_generator_commands.rb
|
|
52
51
|
- lib/stonepath/group.rb
|
|
53
52
|
- lib/stonepath/role.rb
|
|
54
53
|
- lib/stonepath/task.rb
|
|
@@ -56,14 +55,42 @@ files:
|
|
|
56
55
|
- lib/stonepath/work_item.rb
|
|
57
56
|
- lib/stonepath/work_owner.rb
|
|
58
57
|
- rails/init.rb
|
|
59
|
-
- rails_generators/
|
|
60
|
-
- rails_generators/
|
|
61
|
-
- rails_generators/
|
|
62
|
-
- rails_generators/
|
|
63
|
-
- rails_generators/
|
|
64
|
-
- rails_generators/
|
|
65
|
-
- rails_generators/
|
|
66
|
-
- rails_generators/
|
|
58
|
+
- rails_generators/stonepath_event_log/stonepath_event_log_generator.rb
|
|
59
|
+
- rails_generators/stonepath_event_log/templates/create_event_records.rb
|
|
60
|
+
- rails_generators/stonepath_event_log/templates/event_record.rb
|
|
61
|
+
- rails_generators/stonepath_task/USAGE
|
|
62
|
+
- rails_generators/stonepath_task/stonepath_task_generator.rb
|
|
63
|
+
- rails_generators/stonepath_task/templates/generic_task.rb
|
|
64
|
+
- rails_generators/stonepath_task/templates/generic_task_migration.rb
|
|
65
|
+
- rails_generators/stonepath_workitem/USAGE
|
|
66
|
+
- rails_generators/stonepath_workitem/stonepath_workitem_generator.rb
|
|
67
|
+
- rails_generators/stonepath_workitem/templates/actions/create.rb
|
|
68
|
+
- rails_generators/stonepath_workitem/templates/actions/destroy.rb
|
|
69
|
+
- rails_generators/stonepath_workitem/templates/actions/edit.rb
|
|
70
|
+
- rails_generators/stonepath_workitem/templates/actions/index.rb
|
|
71
|
+
- rails_generators/stonepath_workitem/templates/actions/new.rb
|
|
72
|
+
- rails_generators/stonepath_workitem/templates/actions/show.rb
|
|
73
|
+
- rails_generators/stonepath_workitem/templates/actions/update.rb
|
|
74
|
+
- rails_generators/stonepath_workitem/templates/controller.rb
|
|
75
|
+
- rails_generators/stonepath_workitem/templates/event_controller.rb
|
|
76
|
+
- rails_generators/stonepath_workitem/templates/fixtures.yml
|
|
77
|
+
- rails_generators/stonepath_workitem/templates/helper.rb
|
|
78
|
+
- rails_generators/stonepath_workitem/templates/migration.rb
|
|
79
|
+
- rails_generators/stonepath_workitem/templates/model.rb
|
|
80
|
+
- rails_generators/stonepath_workitem/templates/tests/testunit/actions/create.rb
|
|
81
|
+
- rails_generators/stonepath_workitem/templates/tests/testunit/actions/destroy.rb
|
|
82
|
+
- rails_generators/stonepath_workitem/templates/tests/testunit/actions/edit.rb
|
|
83
|
+
- rails_generators/stonepath_workitem/templates/tests/testunit/actions/index.rb
|
|
84
|
+
- rails_generators/stonepath_workitem/templates/tests/testunit/actions/new.rb
|
|
85
|
+
- rails_generators/stonepath_workitem/templates/tests/testunit/actions/show.rb
|
|
86
|
+
- rails_generators/stonepath_workitem/templates/tests/testunit/actions/update.rb
|
|
87
|
+
- rails_generators/stonepath_workitem/templates/tests/testunit/controller.rb
|
|
88
|
+
- rails_generators/stonepath_workitem/templates/tests/testunit/model.rb
|
|
89
|
+
- rails_generators/stonepath_workitem/templates/views/erb/_form.html.erb
|
|
90
|
+
- rails_generators/stonepath_workitem/templates/views/erb/edit.html.erb
|
|
91
|
+
- rails_generators/stonepath_workitem/templates/views/erb/index.html.erb
|
|
92
|
+
- rails_generators/stonepath_workitem/templates/views/erb/new.html.erb
|
|
93
|
+
- rails_generators/stonepath_workitem/templates/views/erb/show.html.erb
|
|
67
94
|
- script/console
|
|
68
95
|
- script/destroy
|
|
69
96
|
- script/generate
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
if Object.const_defined?(:ActionController)
|
|
2
|
-
|
|
3
|
-
module ActionController
|
|
4
|
-
module Resources
|
|
5
|
-
|
|
6
|
-
def define_events_controller(object_sym)
|
|
7
|
-
class_name = object_sym.to_s.classify
|
|
8
|
-
controller_name = class_name + "EventsController"
|
|
9
|
-
|
|
10
|
-
# This is some amazing bit of meta that will probably go away when we have
|
|
11
|
-
# a work_item generator. In short, at runtime, this defines the controller
|
|
12
|
-
# that handles events for something declared in the routes file as a
|
|
13
|
-
# stonepath_workitem
|
|
14
|
-
Object.const_set(controller_name, ApplicationController.clone).class_eval do
|
|
15
|
-
id_name = (class_name.downcase + "_id").to_sym
|
|
16
|
-
#still need generic http error handling
|
|
17
|
-
define_method("create") do
|
|
18
|
-
if request.post?
|
|
19
|
-
@object = get_class(class_name).find(params[id_name])
|
|
20
|
-
event = params[:id]
|
|
21
|
-
if get_class(class_name).aasm_events.keys.include?(event.to_sym)
|
|
22
|
-
respond_to do |format|
|
|
23
|
-
if @object.send(event + "!")
|
|
24
|
-
flash[:notice] = "Event '#{event}' was successfully performed."
|
|
25
|
-
format.html { redirect_to(@object) }
|
|
26
|
-
format.xml { render :xml => @object }
|
|
27
|
-
else
|
|
28
|
-
flash[:notice] = "Event '#{event}' was NOT successfully performed."
|
|
29
|
-
format.html { redirect_to(@object) }
|
|
30
|
-
format.xml { render :xml => @object.errors, :status => :unprocessable_entity }
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def stonepath_workitems(resources_symbol, params={})
|
|
41
|
-
singular_resource_name = resources_symbol.to_s.singularize
|
|
42
|
-
self.resources resources_symbol, params do |o|
|
|
43
|
-
o.resource :event, {:only => "create", :controller => "#{singular_resource_name}_events"}
|
|
44
|
-
end
|
|
45
|
-
define_events_controller(resources_symbol)
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
end
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
class StonepathTaskGenerator < Rails::Generator::Base
|
|
2
|
-
def manifest
|
|
3
|
-
record do |m|
|
|
4
|
-
task_name = args[0]
|
|
5
|
-
m.template('generic_task.rb', "app/models/#{task_name}.rb")
|
|
6
|
-
m.migration_template("generic_task_migration.rb", "db/migrate", :migration_file_name => "create_#{task_name.tableize}")
|
|
7
|
-
end
|
|
8
|
-
end
|
|
9
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
class Create<%= args[0].tableize.classify.pluralize %> < ActiveRecord::Migration
|
|
2
|
-
def self.up
|
|
3
|
-
create_table :<%= args[0].tableize %> do |t|
|
|
4
|
-
|
|
5
|
-
t.string :aasm_state
|
|
6
|
-
t.references :workitem, :polymorphic => true
|
|
7
|
-
t.references :workbench, :polymorphic => true
|
|
8
|
-
|
|
9
|
-
t.datetime :due_at
|
|
10
|
-
t.datetime :completed_at
|
|
11
|
-
t.timestamps
|
|
12
|
-
|
|
13
|
-
# customize your task here
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def self.down
|
|
18
|
-
drop_table :<%= args[0].tableize %>
|
|
19
|
-
end
|
|
20
|
-
end
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
We will eventually have a real generator here that will even include some default config for AASM settings, restful routes for the workflow actions, etc. Until then, it would be best to start a workitem by:
|
|
2
|
-
|
|
3
|
-
1) Using scaffold generator
|
|
4
|
-
2) adding aasm_state:string and owner_id:integer to the migration.
|
|
5
|
-
3) adding:
|
|
6
|
-
|
|
7
|
-
require 'aasm'
|
|
8
|
-
require 'stonepath'
|
|
9
|
-
|
|
10
|
-
stonepath_workitem
|
|
11
|
-
|
|
12
|
-
to the model
|
|
13
|
-
|
|
14
|
-
4) defining a state machine.
|