be_taskable 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'rails', '~> 3.0'
4
+ gem 'state_machine', '~> 1.1'
5
+
6
+ group :development do
7
+ gem 'sqlite3'
8
+ gem 'rspec-rails'
9
+ gem 'rspec-steps'
10
+ gem 'guard'
11
+ gem 'guard-rspec'
12
+ gem 'bundler', '~> 1.2'
13
+ gem 'jeweler', '~> 1.8.4'
14
+ gem 'database_cleaner'
15
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,178 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ actionmailer (3.2.14)
5
+ actionpack (= 3.2.14)
6
+ mail (~> 2.5.4)
7
+ actionpack (3.2.14)
8
+ activemodel (= 3.2.14)
9
+ activesupport (= 3.2.14)
10
+ builder (~> 3.0.0)
11
+ erubis (~> 2.7.0)
12
+ journey (~> 1.0.4)
13
+ rack (~> 1.4.5)
14
+ rack-cache (~> 1.2)
15
+ rack-test (~> 0.6.1)
16
+ sprockets (~> 2.2.1)
17
+ activemodel (3.2.14)
18
+ activesupport (= 3.2.14)
19
+ builder (~> 3.0.0)
20
+ activerecord (3.2.14)
21
+ activemodel (= 3.2.14)
22
+ activesupport (= 3.2.14)
23
+ arel (~> 3.0.2)
24
+ tzinfo (~> 0.3.29)
25
+ activeresource (3.2.14)
26
+ activemodel (= 3.2.14)
27
+ activesupport (= 3.2.14)
28
+ activesupport (3.2.14)
29
+ i18n (~> 0.6, >= 0.6.4)
30
+ multi_json (~> 1.0)
31
+ addressable (2.3.5)
32
+ arel (3.0.2)
33
+ builder (3.0.4)
34
+ coderay (1.0.9)
35
+ database_cleaner (1.1.1)
36
+ diff-lcs (1.2.4)
37
+ erubis (2.7.0)
38
+ faraday (0.8.8)
39
+ multipart-post (~> 1.2.0)
40
+ ffi (1.9.0)
41
+ formatador (0.2.4)
42
+ git (1.2.6)
43
+ github_api (0.10.1)
44
+ addressable
45
+ faraday (~> 0.8.1)
46
+ hashie (>= 1.2)
47
+ multi_json (~> 1.4)
48
+ nokogiri (~> 1.5.2)
49
+ oauth2
50
+ guard (1.8.2)
51
+ formatador (>= 0.2.4)
52
+ listen (>= 1.0.0)
53
+ lumberjack (>= 1.0.2)
54
+ pry (>= 0.9.10)
55
+ thor (>= 0.14.6)
56
+ guard-rspec (3.0.2)
57
+ guard (>= 1.8)
58
+ rspec (~> 2.13)
59
+ hashie (2.0.5)
60
+ highline (1.6.19)
61
+ hike (1.2.3)
62
+ httpauth (0.2.0)
63
+ i18n (0.6.5)
64
+ jeweler (1.8.7)
65
+ builder
66
+ bundler (~> 1.0)
67
+ git (>= 1.2.5)
68
+ github_api (= 0.10.1)
69
+ highline (>= 1.6.15)
70
+ nokogiri (= 1.5.10)
71
+ rake
72
+ rdoc
73
+ journey (1.0.4)
74
+ json (1.8.0)
75
+ jwt (0.1.8)
76
+ multi_json (>= 1.5)
77
+ listen (1.3.0)
78
+ rb-fsevent (>= 0.9.3)
79
+ rb-inotify (>= 0.9)
80
+ rb-kqueue (>= 0.2)
81
+ lumberjack (1.0.4)
82
+ mail (2.5.4)
83
+ mime-types (~> 1.16)
84
+ treetop (~> 1.4.8)
85
+ method_source (0.8.2)
86
+ mime-types (1.25)
87
+ multi_json (1.7.9)
88
+ multi_xml (0.5.5)
89
+ multipart-post (1.2.0)
90
+ nokogiri (1.5.10)
91
+ oauth2 (0.9.2)
92
+ faraday (~> 0.8)
93
+ httpauth (~> 0.2)
94
+ jwt (~> 0.1.4)
95
+ multi_json (~> 1.0)
96
+ multi_xml (~> 0.5)
97
+ rack (~> 1.2)
98
+ polyglot (0.3.3)
99
+ pry (0.9.12.2)
100
+ coderay (~> 1.0.5)
101
+ method_source (~> 0.8)
102
+ slop (~> 3.4)
103
+ rack (1.4.5)
104
+ rack-cache (1.2)
105
+ rack (>= 0.4)
106
+ rack-ssl (1.3.3)
107
+ rack
108
+ rack-test (0.6.2)
109
+ rack (>= 1.0)
110
+ rails (3.2.14)
111
+ actionmailer (= 3.2.14)
112
+ actionpack (= 3.2.14)
113
+ activerecord (= 3.2.14)
114
+ activeresource (= 3.2.14)
115
+ activesupport (= 3.2.14)
116
+ bundler (~> 1.0)
117
+ railties (= 3.2.14)
118
+ railties (3.2.14)
119
+ actionpack (= 3.2.14)
120
+ activesupport (= 3.2.14)
121
+ rack-ssl (~> 1.3.2)
122
+ rake (>= 0.8.7)
123
+ rdoc (~> 3.4)
124
+ thor (>= 0.14.6, < 2.0)
125
+ rake (10.1.0)
126
+ rb-fsevent (0.9.3)
127
+ rb-inotify (0.9.1)
128
+ ffi (>= 0.5.0)
129
+ rb-kqueue (0.2.0)
130
+ ffi (>= 0.5.0)
131
+ rdoc (3.12.2)
132
+ json (~> 1.4)
133
+ rspec (2.13.0)
134
+ rspec-core (~> 2.13.0)
135
+ rspec-expectations (~> 2.13.0)
136
+ rspec-mocks (~> 2.13.0)
137
+ rspec-core (2.13.1)
138
+ rspec-expectations (2.13.0)
139
+ diff-lcs (>= 1.1.3, < 2.0)
140
+ rspec-mocks (2.13.1)
141
+ rspec-rails (2.13.2)
142
+ actionpack (>= 3.0)
143
+ activesupport (>= 3.0)
144
+ railties (>= 3.0)
145
+ rspec-core (~> 2.13.0)
146
+ rspec-expectations (~> 2.13.0)
147
+ rspec-mocks (~> 2.13.0)
148
+ rspec-steps (0.1.0)
149
+ rspec (>= 2.6, < 2.14.0)
150
+ slop (3.4.6)
151
+ sprockets (2.2.2)
152
+ hike (~> 1.2)
153
+ multi_json (~> 1.0)
154
+ rack (~> 1.0)
155
+ tilt (~> 1.1, != 1.3.0)
156
+ sqlite3 (1.3.8)
157
+ state_machine (1.2.0)
158
+ thor (0.18.1)
159
+ tilt (1.4.1)
160
+ treetop (1.4.15)
161
+ polyglot
162
+ polyglot (>= 0.3.1)
163
+ tzinfo (0.3.37)
164
+
165
+ PLATFORMS
166
+ ruby
167
+
168
+ DEPENDENCIES
169
+ bundler (~> 1.2)
170
+ database_cleaner
171
+ guard
172
+ guard-rspec
173
+ jeweler (~> 1.8.4)
174
+ rails (~> 3.0)
175
+ rspec-rails
176
+ rspec-steps
177
+ sqlite3
178
+ state_machine (~> 1.1)
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard 'rspec' do
2
+ watch(%r{^spec/.+_spec\.rb})
3
+ watch(%r{^lib/(.+)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Sebastian
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "be_taskable"
18
+ gem.homepage = "http://github.com/sporto/be_taskable"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Mini framework for creating and maintaining user tasks}
21
+ gem.description = %Q{BeTaskable is a small framework for creating and maintaining tasks / chores / assignments. Meaning something that someone has to do.}
22
+ gem.email = "sebasporto@gmail.com"
23
+ gem.authors = ["Sebastian Porto"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ task :default => :test
36
+
37
+ require 'rdoc/task'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "be_taskable #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.5.0
@@ -0,0 +1,100 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "be_taskable"
8
+ s.version = "0.5.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Sebastian Porto"]
12
+ s.date = "2013-09-02"
13
+ s.description = "BeTaskable is a small framework for creating and maintaining tasks / chores / assignments. Meaning something that someone has to do."
14
+ s.email = "sebasporto@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt"
17
+ ]
18
+ s.files = [
19
+ ".document",
20
+ ".rspec",
21
+ "Gemfile",
22
+ "Gemfile.lock",
23
+ "Guardfile",
24
+ "LICENSE.txt",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "be_taskable.gemspec",
28
+ "docs/task_refresh_activity_diagram.delineato",
29
+ "docs/taskable_complete_flow.delineato",
30
+ "lib/be_taskable.rb",
31
+ "lib/be_taskable/task.rb",
32
+ "lib/be_taskable/task_assignment.rb",
33
+ "lib/be_taskable/task_resolver.rb",
34
+ "lib/be_taskable/task_runner.rb",
35
+ "lib/be_taskable/taskable.rb",
36
+ "lib/be_taskable/tasker.rb",
37
+ "lib/generators/be_taskable/migration_generator.rb",
38
+ "lib/generators/be_taskable/resolver_generator.rb",
39
+ "lib/generators/be_taskable/templates/active_record/migration.rb",
40
+ "lib/generators/be_taskable/templates/resolver.rb.tpl",
41
+ "readme.md",
42
+ "spec/be_taskable/integration/end_to_end_spec.rb",
43
+ "spec/be_taskable/integration/irrelevance_spec.rb",
44
+ "spec/be_taskable/unit/be_taskable_spec.rb",
45
+ "spec/be_taskable/unit/task_assignment_spec.rb",
46
+ "spec/be_taskable/unit/task_runner_spec.rb",
47
+ "spec/be_taskable/unit/task_spec.rb",
48
+ "spec/be_taskable/unit/taskable_spec.rb",
49
+ "spec/be_taskable/unit/tasker_spec.rb",
50
+ "spec/database.yml",
51
+ "spec/models.rb",
52
+ "spec/schema.rb",
53
+ "spec/spec_helper.rb"
54
+ ]
55
+ s.homepage = "http://github.com/sporto/be_taskable"
56
+ s.licenses = ["MIT"]
57
+ s.require_paths = ["lib"]
58
+ s.rubygems_version = "1.8.25"
59
+ s.summary = "Mini framework for creating and maintaining user tasks"
60
+
61
+ if s.respond_to? :specification_version then
62
+ s.specification_version = 3
63
+
64
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
65
+ s.add_runtime_dependency(%q<rails>, ["~> 3.0"])
66
+ s.add_runtime_dependency(%q<state_machine>, ["~> 1.1"])
67
+ s.add_development_dependency(%q<sqlite3>, [">= 0"])
68
+ s.add_development_dependency(%q<rspec-rails>, [">= 0"])
69
+ s.add_development_dependency(%q<rspec-steps>, [">= 0"])
70
+ s.add_development_dependency(%q<guard>, [">= 0"])
71
+ s.add_development_dependency(%q<guard-rspec>, [">= 0"])
72
+ s.add_development_dependency(%q<bundler>, ["~> 1.2"])
73
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
74
+ s.add_development_dependency(%q<database_cleaner>, [">= 0"])
75
+ else
76
+ s.add_dependency(%q<rails>, ["~> 3.0"])
77
+ s.add_dependency(%q<state_machine>, ["~> 1.1"])
78
+ s.add_dependency(%q<sqlite3>, [">= 0"])
79
+ s.add_dependency(%q<rspec-rails>, [">= 0"])
80
+ s.add_dependency(%q<rspec-steps>, [">= 0"])
81
+ s.add_dependency(%q<guard>, [">= 0"])
82
+ s.add_dependency(%q<guard-rspec>, [">= 0"])
83
+ s.add_dependency(%q<bundler>, ["~> 1.2"])
84
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
85
+ s.add_dependency(%q<database_cleaner>, [">= 0"])
86
+ end
87
+ else
88
+ s.add_dependency(%q<rails>, ["~> 3.0"])
89
+ s.add_dependency(%q<state_machine>, ["~> 1.1"])
90
+ s.add_dependency(%q<sqlite3>, [">= 0"])
91
+ s.add_dependency(%q<rspec-rails>, [">= 0"])
92
+ s.add_dependency(%q<rspec-steps>, [">= 0"])
93
+ s.add_dependency(%q<guard>, [">= 0"])
94
+ s.add_dependency(%q<guard-rspec>, [">= 0"])
95
+ s.add_dependency(%q<bundler>, ["~> 1.2"])
96
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
97
+ s.add_dependency(%q<database_cleaner>, [">= 0"])
98
+ end
99
+ end
100
+
@@ -0,0 +1,173 @@
1
+ module BeTaskable
2
+ class Task < ActiveRecord::Base
3
+
4
+ has_many :assignments, class_name: '::BeTaskable::TaskAssignment', dependent: :destroy
5
+ belongs_to :taskable, polymorphic: true
6
+
7
+ scope :completed, where('completed_at IS NOT NULL')
8
+ scope :uncompleted, where(completed_at: nil)
9
+ scope :expired, where('expired_at IS NOT NULL')
10
+ scope :unexpired, where(expired_at: nil)
11
+ # scope :overdue, ->() { where('complete_by IS NOT NULL AND completed_at = NULL AND completed_at < ?', DateTime.now) }
12
+
13
+ validates :taskable_type, presence: true
14
+ validates :taskable_id, presence: true
15
+ validates :action, presence: true #, uniqueness: { scope: [:taskable_type, :taskable_id] }
16
+
17
+ def self.current
18
+ self.uncompleted.unexpired
19
+ end
20
+
21
+ state_machine :state, initial: :open do
22
+ event :complete do
23
+ transition :open => :completed
24
+ end
25
+ event :expire do
26
+ transition :open => :expired
27
+ end
28
+ event :make_irrelevant do
29
+ transition :open => :irrelevant
30
+ end
31
+ event :make_relevant do
32
+ transition :irrelevant => :open
33
+ end
34
+ after_transition :open => :completed, :do => :_on_completion
35
+ after_transition :open => :expired, :do => :_on_expiration
36
+ end
37
+
38
+ #-------------------------------------------------------------------------
39
+ # Actions
40
+ #-------------------------------------------------------------------------
41
+
42
+ # refresh
43
+ # Check that the current assignments are still relevant
44
+ # Create new assignments as needed or deletes them
45
+ # needs to run for irrelevant
46
+ def refresh
47
+ return if completed?
48
+ _runner.refresh
49
+ end
50
+
51
+ # tally
52
+ # Check all the completed assignments and decides wherever to complete the task
53
+ # @return nil if completed
54
+ def tally
55
+ return if completed?
56
+ complete if consensus?
57
+ end
58
+
59
+ # calls refresh and then tally
60
+ # needs to run for irrelevant
61
+ def audit
62
+ return if completed?
63
+ refresh
64
+ tally
65
+ end
66
+
67
+ # completes the assignment for the given assignee
68
+ # @param {Object} assignee
69
+ # @return false if no assignment found
70
+ def complete_by(assignee)
71
+ assignment = assignment_for(assignee)
72
+ return false unless assignment
73
+ assignment.complete
74
+ end
75
+
76
+ # consensus?
77
+ # @return Boolean
78
+ def consensus?
79
+ resolver.consensus?(self)
80
+ end
81
+
82
+ #-------------------------------------------------------------------------
83
+ # Accessors
84
+ #-------------------------------------------------------------------------
85
+
86
+ # @return {Array} List of current assignees for this task
87
+ def assignees
88
+ assignments.map(&:assignee)
89
+ end
90
+
91
+ # @return {String} Gets the label from the resolver for this task
92
+ def label!
93
+ resolver.label_for_task(self)
94
+ end
95
+
96
+ def assignment_for(assignee)
97
+ assignments.where(assignee_id: assignee.id).last
98
+ end
99
+
100
+ def enacted_assignments
101
+ assignments.enacted
102
+ end
103
+
104
+ # resolver
105
+ # @return A resolver instance
106
+ def resolver
107
+ if taskable
108
+ taskable.task_resolver_for_action(action)
109
+ else
110
+ # puts self.id
111
+ # puts self.taskable_id
112
+ # puts self.taskable_type
113
+ # puts self.taskable
114
+ raise "Cannot find taskable"
115
+ end
116
+ end
117
+
118
+ #-------------------------------------------------------------------------
119
+ # Hooks
120
+ #-------------------------------------------------------------------------
121
+
122
+ def on_creation
123
+ resolver.on_creation(self)
124
+ end
125
+
126
+ # hook: called from an assignment when completed
127
+ def on_assignment_completed(assignment)
128
+ tally
129
+ end
130
+
131
+ #-------------------------------------------------------------------------
132
+ # Consensus helpers
133
+ #-------------------------------------------------------------------------
134
+
135
+ def all_assignments_done?
136
+ assignments.all?{ |a| a.completed? }
137
+ end
138
+
139
+ def any_assignment_done?
140
+ assignments.any?{ |a| a.completed? }
141
+ end
142
+
143
+ def majority_of_assignments_done?
144
+ done = assignments.find_all{ |a| a.completed? }
145
+ done.size > (assignments.size.to_f / 2)
146
+ end
147
+
148
+ #-------------------------------------------------------------------------
149
+ # Pseudo private
150
+ #-------------------------------------------------------------------------
151
+
152
+ def _runner
153
+ @runner ||= BeTaskable::TaskRunner.new(self)
154
+ end
155
+
156
+ # called when the task is marked as complete by the state machine
157
+ def _on_completion
158
+ self.update_attribute(:completed_at, DateTime.now)
159
+ assignments.update_all(completed_at: DateTime.now)
160
+ resolver.on_completion(self)
161
+ end
162
+
163
+ # expires the task and all the assignments
164
+ def _on_expiration
165
+ self.update_attribute(:expired_at, DateTime.now)
166
+ assignments.each do |assignment|
167
+ assignment.expire
168
+ end
169
+ resolver.on_expiration(self)
170
+ end
171
+
172
+ end
173
+ end
@@ -0,0 +1,60 @@
1
+ module BeTaskable
2
+ class TaskAssignment < ActiveRecord::Base
3
+ belongs_to :task, class_name: '::BeTaskable::Task'
4
+ belongs_to :assignee, polymorphic: true
5
+
6
+ scope :completed, where('completed_at IS NOT NULL')
7
+ scope :uncompleted, where(completed_at: nil)
8
+ scope :expired, where('expired_at IS NOT NULL')
9
+ scope :unexpired, where(expired_at: nil)
10
+ scope :unconfirmed, where(confirmed: [nil, false])
11
+ scope :visible, ->{ where('visible_at IS NULL OR visible_at < ?', DateTime.now.to_formatted_s(:db)) }
12
+ scope :overdue, ->{ where('complete_by < ? AND completed_at IS NULL', DateTime.now.to_formatted_s(:db)) }
13
+ scope :not_overdue, ->{ where('complete_by IS NULL OR complete_by > ?', DateTime.now.to_formatted_s(:db)) }
14
+ scope :enacted, where(enacted: true)
15
+
16
+ def self.current
17
+ self.uncompleted.unexpired.not_overdue.visible
18
+ end
19
+
20
+ # @return {Boolean}
21
+ def completed?
22
+ !!completed_at
23
+ end
24
+
25
+ # @return {Boolean}
26
+ def visible?
27
+ self.class.visible.exists?(self)
28
+ end
29
+
30
+ # completes the assignment by the assignee
31
+ # it triggers a hook in task (on_assignment_complete)
32
+ def complete
33
+ return false if completed?
34
+ self.update_attribute(:completed_at, DateTime.now)
35
+ self.update_attribute(:enacted, true)
36
+ task.on_assignment_completed(self)
37
+ true
38
+ end
39
+
40
+ # Gets the label from the resolver
41
+ def label!
42
+ resolver.label_for_assignment(self)
43
+ end
44
+
45
+ # Gets the url from the resolver
46
+ def url!
47
+ resolver.url_for_assignment(self)
48
+ end
49
+
50
+ # @return {Object} A resolver instance
51
+ def resolver
52
+ task.resolver
53
+ end
54
+
55
+ def taskable
56
+ task.taskable
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,47 @@
1
+ module BeTaskable
2
+ class TaskResolver
3
+
4
+ def consensus?(task)
5
+ raise NotImplementedError
6
+ end
7
+
8
+ def is_task_relevant?(task)
9
+ true
10
+ end
11
+
12
+ def assignees_for_task(task)
13
+ [] #raise NotImplementedError
14
+ end
15
+
16
+ def due_date_for_assignment(assignment)
17
+ nil
18
+ end
19
+
20
+ def visible_date_for_assignment(assignment)
21
+ nil
22
+ end
23
+
24
+ def label_for_task(task)
25
+ ""
26
+ end
27
+
28
+ def label_for_assignment(assignment)
29
+ ""
30
+ end
31
+
32
+ def url_for_assignment(assignment)
33
+ ""
34
+ end
35
+
36
+ # hooks
37
+ def on_creation(task)
38
+ end
39
+
40
+ def on_completion(task)
41
+ end
42
+
43
+ def on_expiration(task)
44
+ end
45
+
46
+ end
47
+ end