bumbleworks 0.0.66 → 0.0.67

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.
@@ -1,45 +1,67 @@
1
1
  module Bumbleworks
2
2
  class Task
3
3
  class Finder
4
+ class WorkitemQuery < Proc; end
5
+ class TaskQuery < Proc; end
6
+
7
+ WhereKeyToMethodMap = {
8
+ :available => :available,
9
+ :unavailable => :unavailable,
10
+ :nickname => :by_nickname,
11
+ :roles => :for_roles,
12
+ :role => :for_role,
13
+ :unclaimed => :unclaimed,
14
+ :claimed => :claimed,
15
+ :fields => :with_fields,
16
+ :claimant => :for_claimant,
17
+ :entity => :for_entity,
18
+ :processes => :for_processes,
19
+ :process => :for_process,
20
+ :completable => :completable
21
+ }
22
+
4
23
  include Enumerable
5
24
 
6
25
  def initialize(task_class = Bumbleworks::Task)
7
26
  @task_class = task_class
8
27
  @queries = []
9
- @task_filters = []
10
28
  @orderers = []
11
29
  @wfids = nil
12
- add_query { |wi| wi['fields']['params']['task'] }
13
- end
14
-
15
- def where(filters)
16
- key_method_map = {
17
- :available => :available,
18
- :nickname => :by_nickname,
19
- :roles => :for_roles,
20
- :role => :for_role,
21
- :unclaimed => :unclaimed,
22
- :claimed => :claimed,
23
- :fields => :with_fields,
24
- :claimant => :for_claimant,
25
- :entity => :for_entity,
26
- :processes => :for_processes,
27
- :process => :for_process,
28
- :completable => :completable
29
- }
30
- fields = filters.select { |k,v| !key_method_map.keys.include? k }
31
- methods = filters.select { |k,v| key_method_map.keys.include? k }
32
- query = methods.inject(self) { |query, (method, args)|
33
- query.send(key_method_map[method], args)
30
+ @join = :all
31
+ end
32
+
33
+ def where_any(query_group = {})
34
+ set_join_for_query_group(query_group, :any)
35
+ end
36
+
37
+ def where_all(query_group = {})
38
+ set_join_for_query_group(query_group, :all)
39
+ end
40
+
41
+ def where(filters, group_type = nil)
42
+ group_type = :all unless group_type == :any
43
+ new_finder = self.class.new(@task_class)
44
+ new_finder.send(:"where_#{group_type}")
45
+ new_finder = filters.inject(new_finder) { |finder, (key, args)|
46
+ if method = WhereKeyToMethodMap[key]
47
+ finder.send(method, args)
48
+ else
49
+ finder.with_fields(key => args)
50
+ end
34
51
  }
35
- unless fields.empty?
36
- query.with_fields(fields)
52
+ add_subfinder new_finder
53
+ end
54
+
55
+ def available(check = true)
56
+ if check
57
+ where_all(:unclaimed => true, :completable => true)
58
+ else
59
+ where_any(:claimed => true, :completable => false)
37
60
  end
38
- query
39
61
  end
40
62
 
41
- def available
42
- unclaimed.completable
63
+ def unavailable(check = true)
64
+ available(!check)
43
65
  end
44
66
 
45
67
  def by_nickname(nickname)
@@ -48,6 +70,7 @@ module Bumbleworks
48
70
 
49
71
  def for_roles(identifiers)
50
72
  identifiers ||= []
73
+ identifiers.map! { |i| i.to_s }
51
74
  add_query { |wi| identifiers.include?(wi['participant_name']) }
52
75
  end
53
76
 
@@ -110,13 +133,18 @@ module Bumbleworks
110
133
  add_filter { |task| task.completable? == true_or_false }
111
134
  end
112
135
 
136
+ def add_subfinder(finder)
137
+ @queries << finder
138
+ self
139
+ end
140
+
113
141
  def add_query(&block)
114
- @queries << block
142
+ @queries << WorkitemQuery.new(&block)
115
143
  self
116
144
  end
117
145
 
118
146
  def add_filter(&block)
119
- @task_filters << block
147
+ @queries << TaskQuery.new(&block)
120
148
  self
121
149
  end
122
150
 
@@ -155,10 +183,14 @@ module Bumbleworks
155
183
  !any?
156
184
  end
157
185
 
186
+ def check_queries(workitem, task)
187
+ grouped_queries(@join).call(workitem, task)
188
+ end
189
+
158
190
  private
159
191
 
160
192
  def add_orderer(fields, field_type = 'fields')
161
- @orderers << proc { |wi_x, wi_y|
193
+ @orderers << Proc.new { |wi_x, wi_y|
162
194
  relevant_direction, result = :asc, 0
163
195
  fields.each do |field, direction|
164
196
  sets = [wi_x['fields'], wi_y['fields']]
@@ -173,14 +205,25 @@ module Bumbleworks
173
205
  end
174
206
 
175
207
  def filtered_task_from_raw_workitem(workitem)
176
- if @queries.all? { |q| q.call(workitem) }
177
- task = from_workitem(::Ruote::Workitem.new(workitem))
178
- task if check_filters(task)
179
- end
180
- end
181
-
182
- def check_filters(task)
183
- @task_filters.all? { |f| f.call(task) }
208
+ task = from_workitem(::Ruote::Workitem.new(workitem))
209
+ task if check_queries(workitem, task)
210
+ end
211
+
212
+ def grouped_queries(group_type)
213
+ Proc.new { |wi, task|
214
+ @queries.send(:"#{group_type}?") { |q|
215
+ case q
216
+ when WorkitemQuery
217
+ q.call(wi)
218
+ when TaskQuery
219
+ q.call(task)
220
+ when self.class
221
+ q.check_queries(wi, task)
222
+ else
223
+ raise "Unrecognized query type"
224
+ end
225
+ }
226
+ }
184
227
  end
185
228
 
186
229
  def from_workitem(workitem)
@@ -188,7 +231,22 @@ module Bumbleworks
188
231
  end
189
232
 
190
233
  def raw_workitems(wfids)
191
- Bumbleworks.dashboard.context.storage.get_many('workitems', wfids)
234
+ Bumbleworks.dashboard.context.storage.get_many('workitems', wfids).select { |wi|
235
+ wi['fields']['params']['task']
236
+ }
237
+ end
238
+
239
+ def join=(new_join)
240
+ @join = new_join if [:all, :any].include?(new_join)
241
+ end
242
+
243
+ def set_join_for_query_group(query_group, type)
244
+ if query_group.empty?
245
+ self.join = type
246
+ self
247
+ else
248
+ where(query_group, type)
249
+ end
192
250
  end
193
251
  end
194
252
  end
@@ -1,3 +1,3 @@
1
1
  module Bumbleworks
2
- VERSION = "0.0.66"
2
+ VERSION = "0.0.67"
3
3
  end
@@ -14,6 +14,15 @@ describe Bumbleworks::Task::Finder do
14
14
  end
15
15
  end
16
16
 
17
+ describe '#check_queries' do
18
+ it 'raises an exception in case a query type is unrecognized' do
19
+ subject.instance_variable_set(:@queries, ['not a real query'])
20
+ expect {
21
+ subject.check_queries(:wi, :task)
22
+ }.to raise_error("Unrecognized query type")
23
+ end
24
+ end
25
+
17
26
  describe '#add_query' do
18
27
  it 'adds given block as new raw workitem query' do
19
28
  Bumbleworks.launch!('dog-lifecycle')
@@ -44,6 +53,19 @@ describe Bumbleworks::Task::Finder do
44
53
  end
45
54
  end
46
55
 
56
+ describe '#add_subfinder' do
57
+ it 'adds given finder as new sub' do
58
+ Bumbleworks.launch!('dog-lifecycle')
59
+ Bumbleworks.dashboard.wait_for(:cat)
60
+ finder = subject.add_subfinder(
61
+ Bumbleworks::Task::Finder.new.for_role(:cat)
62
+ )
63
+ finder.map(&:nickname).should =~ [
64
+ 'skip_and_jump'
65
+ ]
66
+ end
67
+ end
68
+
47
69
  describe '#all' do
48
70
  it 'uses Bumbleworks::Task class by default for task generation' do
49
71
  Bumbleworks.launch!('dog-lifecycle')
@@ -64,26 +86,64 @@ describe Bumbleworks::Task::Finder do
64
86
 
65
87
  describe '#available' do
66
88
  it 'adds both unclaimed and completable filters' do
67
- subject.should_receive(:unclaimed).and_return(subject)
68
- subject.should_receive(:completable).and_return(subject)
89
+ subject.should_receive(:where_all).with(:unclaimed => true, :completable => true).and_return(subject)
69
90
  subject.available
70
91
  end
92
+
93
+ it 'adds OR-ed claimed and not-completable filters if passed false' do
94
+ subject.should_receive(:where_any).with(:claimed => true, :completable => false).and_return(subject)
95
+ subject.available(false)
96
+ end
97
+ end
98
+
99
+ describe '#unavailable' do
100
+ it 'checks if not available' do
101
+ subject.should_receive(:available).with(false).and_return(subject)
102
+ subject.unavailable
103
+ end
104
+
105
+ it 'checks if available when passed false' do
106
+ subject.should_receive(:available).with(true).and_return(subject)
107
+ subject.unavailable(false)
108
+ end
109
+ end
110
+
111
+ [:all, :any].each do |join_type|
112
+ describe "#where_#{join_type}" do
113
+ it "sets join to #{join_type} if no args" do
114
+ subject.should_receive(:join=).with(join_type)
115
+ subject.send(:"where_#{join_type}")
116
+ end
117
+
118
+ it "calls where with :#{join_type} type if args" do
119
+ subject.should_receive(:where).with(:filters, join_type)
120
+ subject.send(:"where_#{join_type}", :filters)
121
+ end
122
+ end
71
123
  end
72
124
 
73
125
  describe '#where' do
74
- it 'compiles a finder' do
75
- subject.should_receive(:available).and_return(subject)
76
- subject.should_receive(:by_nickname).with(:nicholas).and_return(subject)
77
- subject.should_receive(:for_roles).with([:dinner, :barca]).and_return(subject)
78
- subject.should_receive(:unclaimed).and_return(subject)
79
- subject.should_receive(:claimed).and_return(subject)
80
- subject.should_receive(:for_claimant).with(:dr_clam).and_return(subject)
81
- subject.should_receive(:for_entity).with(:a_luffly_pirate).and_return(subject)
82
- subject.should_receive(:for_processes).with([:jasmine, :mulan]).and_return(subject)
83
- subject.should_receive(:completable).with(true).and_return(subject)
84
- subject.should_receive(:with_fields).with({ :horse => :giant_pony, :pie => :silly_cake }).and_return(subject)
85
- subject.where({
126
+ it 'creates a new finder and adds it to queries' do
127
+ parent = described_class.new(:a_class)
128
+ child = described_class.new
129
+ described_class.stub(:new).with(:a_class).and_return(child)
130
+ child.should_receive(:where_all)
131
+ child.should_receive(:available).and_return(child)
132
+ child.should_receive(:unavailable).and_return(child)
133
+ child.should_receive(:by_nickname).with(:nicholas).and_return(child)
134
+ child.should_receive(:for_roles).with([:dinner, :barca]).and_return(child)
135
+ child.should_receive(:unclaimed).and_return(child)
136
+ child.should_receive(:claimed).and_return(child)
137
+ child.should_receive(:for_claimant).with(:dr_clam).and_return(child)
138
+ child.should_receive(:for_entity).with(:a_luffly_pirate).and_return(child)
139
+ child.should_receive(:for_processes).with([:jasmine, :mulan]).and_return(child)
140
+ child.should_receive(:completable).with(true).and_return(child)
141
+ child.should_receive(:with_fields).with(:horse => :giant_pony).and_return(child)
142
+ child.should_receive(:with_fields).with(:pie => :silly_cake).and_return(child)
143
+ parent.should_receive(:add_subfinder).with(child)
144
+ parent.where({
86
145
  :available => true,
146
+ :unavailable => true,
87
147
  :nickname => :nicholas,
88
148
  :roles => [:dinner, :barca],
89
149
  :unclaimed => true,
@@ -335,7 +335,15 @@ describe Bumbleworks::Task do
335
335
  it 'returns tasks for all given roles' do
336
336
  Bumbleworks.dashboard.wait_for(:father)
337
337
  tasks = described_class.for_roles(['heckler', 'mother'])
338
- tasks.should have(2).items
338
+ tasks.map(&:nickname).should == [
339
+ 'comment_on_dancing_ability',
340
+ 'ignore_pleas_for_attention'
341
+ ]
342
+ end
343
+
344
+ it 'works with symbolized role names' do
345
+ Bumbleworks.dashboard.wait_for(:father)
346
+ tasks = described_class.for_roles([:heckler, :mother])
339
347
  tasks.map(&:nickname).should == [
340
348
  'comment_on_dancing_ability',
341
349
  'ignore_pleas_for_attention'
@@ -600,7 +608,7 @@ describe Bumbleworks::Task do
600
608
  described_class.new(workflow_item).nickname.should == 'go_to_work'
601
609
  end
602
610
 
603
- it 'is immutable; cannot be changed by modified the param' do
611
+ it 'is immutable; cannot be changed by modifying the param' do
604
612
  task = described_class.new(workflow_item)
605
613
  task.nickname.should == 'go_to_work'
606
614
  task.params['task'] = 'what_is_wrong_with_you?'
@@ -923,7 +931,7 @@ describe Bumbleworks::Task do
923
931
  end
924
932
 
925
933
  describe 'chained queries' do
926
- it 'allows for AND-ed chained finders' do
934
+ before(:each) do
927
935
  module BeProudTask
928
936
  def completable?
929
937
  role == 'pink'
@@ -945,33 +953,51 @@ describe Bumbleworks::Task do
945
953
  described_class.by_nickname('be_really_mad').first.claim('crayon_box')
946
954
  described_class.by_nickname('be_a_bit_sad').first.claim('crayon_box')
947
955
  described_class.by_nickname('be_scared').first.claim('crayon_box')
956
+ end
948
957
 
958
+ it 'allows for AND-ed chained finders' do
949
959
  tasks = described_class.
950
960
  for_roles(['green', 'pink']).
951
961
  by_nickname('be_proud')
952
- tasks.should have(2).items
953
962
  tasks.map(&:nickname).should =~ ['be_proud', 'be_proud']
954
963
 
955
964
  tasks = described_class.
956
965
  for_roles(['green', 'pink', 'blue']).
957
966
  completable.
958
967
  by_nickname('be_proud')
959
- tasks.should have(1).items
960
968
  tasks.map(&:nickname).should =~ ['be_proud']
961
969
  tasks.first.role.should == 'pink'
962
970
 
963
971
  tasks = described_class.
964
972
  for_claimant('crayon_box').
965
973
  for_roles(['red', 'yellow', 'green'])
966
- tasks.should have(2).items
967
974
  tasks.map(&:nickname).should =~ ['be_really_mad', 'be_scared']
968
975
 
969
976
  tasks = described_class.
970
977
  for_claimant('crayon_box').
971
978
  by_nickname('be_a_bit_sad').
972
979
  for_role('blue')
973
- tasks.should have(1).item
974
- tasks.first.nickname.should == 'be_a_bit_sad'
980
+ tasks.map(&:nickname).should == ['be_a_bit_sad']
981
+ end
982
+
983
+ it 'allows for OR-ed chained finders' do
984
+ tasks = described_class.where_any.
985
+ for_role('blue').
986
+ by_nickname('be_proud')
987
+ tasks.map(&:nickname).should =~ ['be_a_bit_sad', 'be_proud', 'be_proud']
988
+
989
+ tasks = described_class.where_any.
990
+ completable.
991
+ claimed
992
+ tasks.map(&:nickname).should =~ ['be_really_mad', 'be_scared', 'be_a_bit_sad', 'be_envious', 'be_proud']
993
+ end
994
+
995
+ it 'allows for combination of AND-ed and OR-ed finders' do
996
+ tasks = described_class.
997
+ for_claimant('crayon_box').
998
+ for_roles(['red', 'yellow', 'green']).
999
+ where_any(:nickname => 'spittle', :role => 'red')
1000
+ tasks.map(&:nickname).should =~ ['be_really_mad']
975
1001
  end
976
1002
  end
977
1003
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bumbleworks
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.66
4
+ version: 0.0.67
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -263,7 +263,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
263
263
  version: '0'
264
264
  segments:
265
265
  - 0
266
- hash: 2932416293581742499
266
+ hash: -828437829805338939
267
267
  required_rubygems_version: !ruby/object:Gem::Requirement
268
268
  none: false
269
269
  requirements:
@@ -272,7 +272,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
272
272
  version: '0'
273
273
  segments:
274
274
  - 0
275
- hash: 2932416293581742499
275
+ hash: -828437829805338939
276
276
  requirements: []
277
277
  rubyforge_project:
278
278
  rubygems_version: 1.8.23