be_taskable 0.5.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/.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