stonepath 0.0.3 → 0.0.4
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/group.rb +9 -0
- data/lib/stonepath/role.rb +4 -0
- data/lib/stonepath/task.rb +22 -8
- data/lib/stonepath/work_bench.rb +1 -1
- data/lib/stonepath/work_item.rb +29 -19
- data/lib/stonepath/work_owner.rb +7 -0
- data/stonepath.gemspec +2 -1
- data/stonepath.pdf +0 -0
- data/test/app_root/app/models/assignment.rb +1 -1
- data/test/app_root/app/models/case.rb +13 -1
- data/test/app_root/app/models/custom_assignment.rb +0 -1
- data/test/app_root/db/migrate/02_create_assignments.rb +5 -1
- data/test/app_root/db/migrate/03_create_cases.rb +2 -0
- data/test/task_test.rb +47 -0
- data/test/workitem_test.rb +6 -0
- metadata +2 -1
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.4
|
data/lib/stonepath/group.rb
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
# This is a concept that existed in the older Journeyman workflow engine, but I'm not sure
|
2
|
+
# that StonePath needs it. It is proving more worthwhile to ust rely on any number of other
|
3
|
+
# active_record models for providing group functionality, and you can see this id pretty much
|
4
|
+
# an empty stub.
|
5
|
+
|
6
|
+
# Groups were another aggregation of work much like users were. With the general concept of
|
7
|
+
# WorkBench, I think this will be leaving the framework soon.
|
8
|
+
# -db!
|
9
|
+
|
1
10
|
module StonePath
|
2
11
|
module Group
|
3
12
|
def self.included(base)
|
data/lib/stonepath/role.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# This is a concept that existed in the older Journeyman workflow engine, but I'm not sure
|
2
|
+
# that StonePath needs it. It is proving more worthwhile to ust rely on any number of other
|
3
|
+
# gems for providing role functionality, and you can see this id pretty much an empty stub.
|
4
|
+
|
1
5
|
module StonePath
|
2
6
|
module Role
|
3
7
|
def self.included(base)
|
data/lib/stonepath/task.rb
CHANGED
@@ -1,11 +1,21 @@
|
|
1
|
+
# A Task in this framework is simply a relation between a workitem and a workbench. It has
|
2
|
+
# some default workflow, and should be extended with whatever attributes make sense for the
|
3
|
+
# business domain you are modeling.
|
4
|
+
|
1
5
|
module StonePath
|
2
6
|
module SPTask
|
3
7
|
|
8
|
+
# This will move from here shortly, into another class/module for containing things like this.
|
9
|
+
# This is the workflow definition for a default task. This is defined this way so that users
|
10
|
+
# can provide their own task workflow definition as a block to the stonepath_task declaration.
|
11
|
+
# This lanbda is passed in if the user doesn't provide anything.
|
12
|
+
# It is possible that we will identify other useful options and want to provide them as config
|
13
|
+
# blocks in the StonePath gem.
|
4
14
|
def self.default_config_block
|
5
15
|
lambda {
|
6
16
|
aasm_initial_state :active
|
7
17
|
aasm_state :active, :after_enter => :notify_created
|
8
|
-
aasm_state :completed, :
|
18
|
+
aasm_state :completed, :after_enter => [:timestamp_complete, :notify_closed]
|
9
19
|
aasm_state :expired, :after_enter => :notify_closed
|
10
20
|
aasm_state :cancelled, :after_enter => :notify_closed
|
11
21
|
|
@@ -31,16 +41,20 @@ module StonePath
|
|
31
41
|
}
|
32
42
|
end
|
33
43
|
|
44
|
+
|
34
45
|
def self.included(base)
|
35
46
|
base.instance_eval do
|
36
47
|
|
37
|
-
|
48
|
+
# Tasks are now completely polymorphic between workbenches.
|
49
|
+
# as long as an activerecord model declares itself as a workbench and declares itself
|
50
|
+
# a workbench for the specific kind of task, everything just works.
|
51
|
+
belongs_to :workbench, :polymorphic => true
|
52
|
+
|
53
|
+
# Tasks are now completely polymorphic between workitems.
|
54
|
+
# as long as an activerecord model declares itself as a workitem and declares itself
|
55
|
+
# a workitem for the specific kind of task, everything just works.
|
56
|
+
belongs_to :workitem, :polymorphic => true
|
38
57
|
|
39
|
-
def task_for(workitem, options={})
|
40
|
-
options.merge!(:class_name => workitem.to_s.classify)
|
41
|
-
belongs_to :workitem, options
|
42
|
-
end
|
43
|
-
|
44
58
|
def audits_transitions
|
45
59
|
puts "#{self.class} audits transitions"
|
46
60
|
end
|
@@ -68,7 +82,7 @@ module StonePath
|
|
68
82
|
end
|
69
83
|
|
70
84
|
def notify_closed
|
71
|
-
|
85
|
+
if workitem.respond_to?(:task_closed)
|
72
86
|
workitem.task_closed(self)
|
73
87
|
end
|
74
88
|
end
|
data/lib/stonepath/work_bench.rb
CHANGED
data/lib/stonepath/work_item.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# The WorkItem is the center of this framework. It is the thing that has a workflow,
|
2
|
+
# is the subject of ownership and tasks. Tis is the place the primaey state machine will
|
3
|
+
# exist
|
4
|
+
|
1
5
|
module StonePath
|
2
6
|
module WorkItem
|
3
7
|
def self.included(base)
|
@@ -9,15 +13,12 @@ module StonePath
|
|
9
13
|
belongs_to :owner, options
|
10
14
|
end
|
11
15
|
|
12
|
-
def
|
13
|
-
has_many tasks,
|
16
|
+
def tasked_through(tasks, options={})
|
17
|
+
has_many tasks, :as => :workitem
|
14
18
|
end
|
15
19
|
|
16
20
|
def stonepath_acl()
|
17
21
|
require File.expand_path(File.dirname(__FILE__)) + "/acl.rb"
|
18
|
-
#require File.expand_path(File.dirname(__FILE__)) + "/acl/acl.rb"
|
19
|
-
#require File.expand_path(File.dirname(__FILE__)) + "/acl/acl_role.rb"
|
20
|
-
#require File.expand_path(File.dirname(__FILE__)) + "/acl/acl_state.rb"
|
21
22
|
cattr_accessor :acl
|
22
23
|
self.acl = StonePath::ACL::Controller.new(self)
|
23
24
|
yield self.acl
|
@@ -31,23 +32,32 @@ module StonePath
|
|
31
32
|
class << self
|
32
33
|
alias_method "define_attribute_methods_without_hook", "define_attribute_methods"
|
33
34
|
alias_method "define_attribute_methods", "define_attribute_methods_with_hook"
|
35
|
+
end
|
36
|
+
end #base.instance_eval
|
37
|
+
|
38
|
+
def allowed?(method)
|
39
|
+
acl.allowed?(aasm_current_state, current_user, method)
|
40
|
+
end
|
41
|
+
|
42
|
+
# modifies to_xml do that it includes all the possible events from this state.
|
43
|
+
# useful when you are using WorkItems as resources with ActiveResource
|
44
|
+
def to_xml_with_events
|
45
|
+
to_xml_without_events do |xml|
|
46
|
+
xml.aasm_events_for_current_state(:type=>"array") do
|
47
|
+
aasm_events_for_current_state.each do |e|
|
48
|
+
xml.aasm_event do
|
49
|
+
xml.name e.to_s
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
34
53
|
end
|
35
54
|
end
|
36
55
|
|
37
|
-
|
38
|
-
|
56
|
+
base.instance_eval do
|
57
|
+
alias_method_chain :to_xml, :events
|
39
58
|
end
|
40
59
|
|
41
|
-
end
|
60
|
+
end #self.included
|
61
|
+
|
42
62
|
end
|
43
|
-
end
|
44
|
-
|
45
|
-
|
46
|
-
# if table_exists? <workitem>_transition_log_entries
|
47
|
-
#define WorkItem::TransitionLogEntry
|
48
|
-
# then for each transition method, have an after proc that
|
49
|
-
# creates workitem_transition_log
|
50
|
-
# workitem_id
|
51
|
-
# transitioned_to
|
52
|
-
# transitioned_by
|
53
|
-
# transitioned_at
|
63
|
+
end
|
data/lib/stonepath/work_owner.rb
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# every WorkItem has one and exactly one owner. In some domains, WorkOwners and WorkBenches will
|
2
|
+
# be the same thing, but in other domains they are separate concepts. the owner is 'responsible'
|
3
|
+
# for the WorkItem in a larger sense - but the WorkBenches are 'responsible' for the completion of
|
4
|
+
# tasks associated with the WorkItem.
|
5
|
+
#
|
6
|
+
# This separation allows workflows where the owner assigns out work, and may oe may not be
|
7
|
+
# responsible for the actual completion of the work.
|
1
8
|
module StonePath
|
2
9
|
module WorkOwner
|
3
10
|
def self.included(base)
|
data/stonepath.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{stonepath}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["David Bock"]
|
@@ -42,6 +42,7 @@ Gem::Specification.new do |s|
|
|
42
42
|
"script/destroy",
|
43
43
|
"script/generate",
|
44
44
|
"stonepath.gemspec",
|
45
|
+
"stonepath.pdf",
|
45
46
|
"test/acl_test.rb",
|
46
47
|
"test/app_root/app/controllers/application_controller.rb",
|
47
48
|
"test/app_root/app/models/assignment.rb",
|
data/stonepath.pdf
ADDED
Binary file
|
@@ -18,7 +18,7 @@ class Case < ActiveRecord::Base
|
|
18
18
|
end
|
19
19
|
|
20
20
|
owned_by :user
|
21
|
-
|
21
|
+
tasked_through :assignments
|
22
22
|
|
23
23
|
|
24
24
|
|
@@ -63,5 +63,17 @@ class Case < ActiveRecord::Base
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
+
|
67
|
+
def task_created(task)
|
68
|
+
self.notification_method = "created"
|
69
|
+
self.notified_id = task.id
|
70
|
+
self.save
|
71
|
+
end
|
66
72
|
|
73
|
+
def task_closed(task)
|
74
|
+
self.notification_method = "closed"
|
75
|
+
self.notified_id = task.id
|
76
|
+
self.save
|
77
|
+
end
|
78
|
+
|
67
79
|
end
|
@@ -3,8 +3,12 @@ class CreateAssignments < ActiveRecord::Migration
|
|
3
3
|
def self.up
|
4
4
|
create_table :assignments do |t|
|
5
5
|
t.string :aasm_state
|
6
|
-
t.integer :
|
6
|
+
t.integer :workitem_id
|
7
|
+
t.string :workitem_type
|
8
|
+
t.integer :workbench_id
|
9
|
+
t.string :workbench_type
|
7
10
|
t.datetime :completed_at
|
11
|
+
t.datetime :due_at
|
8
12
|
t.timestamps
|
9
13
|
end
|
10
14
|
end
|
data/test/task_test.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
2
|
|
3
|
+
require 'flexmock/test_unit'
|
4
|
+
|
3
5
|
class TaskTest < Test::Unit::TestCase
|
4
6
|
|
5
7
|
def setup
|
@@ -38,6 +40,51 @@ class TaskTest < Test::Unit::TestCase
|
|
38
40
|
assert_equal("expired", a.aasm_state)
|
39
41
|
end
|
40
42
|
|
43
|
+
should "be overdue? if due_at is in the past" do
|
44
|
+
c = Case.create
|
45
|
+
a = c.assignments.create(:due_at => 1.week.ago)
|
46
|
+
assert(a.overdue?)
|
47
|
+
end
|
48
|
+
|
49
|
+
should "be able to set up the relationship between a case and an assignment" do
|
50
|
+
c = Case.create
|
51
|
+
a = c.assignments.create
|
52
|
+
assert_equal(a, c.assignments[0])
|
53
|
+
assert_equal(c, c.assignments[0].workitem)
|
54
|
+
end
|
55
|
+
|
56
|
+
should "be able to set up the relationship between a user (as a workbench) and an assignment" do
|
57
|
+
u = User.create
|
58
|
+
c = Case.create
|
59
|
+
a = c.assignments.create(:workbench => u)
|
60
|
+
|
61
|
+
assert_equal(a, u.assignments[0])
|
62
|
+
assert_equal(u, a.workbench)
|
63
|
+
end
|
64
|
+
|
65
|
+
# This whole event notification thing is ugly.
|
66
|
+
# Putting aside the ugly way I tested this, the whole AASM callback mechanism
|
67
|
+
# has a problem that the id isn't set after the callback from a create.
|
68
|
+
# Looking at the code of aasm, I cannot easily figure out why.
|
69
|
+
should "callback the workitem when a task is created" do
|
70
|
+
c = Case.create
|
71
|
+
cid = c.id
|
72
|
+
a = c.assignments.create
|
73
|
+
c = Case.find cid
|
74
|
+
assert_equal("created", c.notification_method)
|
75
|
+
#assert_equal(a.id, c.notified_id)
|
76
|
+
end
|
77
|
+
|
78
|
+
should "callback the workitem when a task is completed" do
|
79
|
+
c = Case.create
|
80
|
+
cid = c.id
|
81
|
+
a = c.assignments.create
|
82
|
+
a.complete!
|
83
|
+
c = Case.find cid
|
84
|
+
assert_equal("closed", c.notification_method)
|
85
|
+
#assert_equal(a.id, c.notified_id)
|
86
|
+
end
|
87
|
+
|
41
88
|
end
|
42
89
|
|
43
90
|
|
data/test/workitem_test.rb
CHANGED
@@ -8,4 +8,10 @@ class WorkitemTest < Test::Unit::TestCase
|
|
8
8
|
should "not do much of anything yet" do
|
9
9
|
c = Case.new
|
10
10
|
end
|
11
|
+
|
12
|
+
should "contain xml for the possible events" do
|
13
|
+
c = Case.create
|
14
|
+
xml = c.to_xml
|
15
|
+
assert(xml.include?("<aasm_events_for_current_state type=\"array\">"))
|
16
|
+
end
|
11
17
|
end
|
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.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Bock
|
@@ -57,6 +57,7 @@ files:
|
|
57
57
|
- script/destroy
|
58
58
|
- script/generate
|
59
59
|
- stonepath.gemspec
|
60
|
+
- stonepath.pdf
|
60
61
|
- test/acl_test.rb
|
61
62
|
- test/app_root/app/controllers/application_controller.rb
|
62
63
|
- test/app_root/app/models/assignment.rb
|