bumbleworks 0.0.66 → 0.0.67

Sign up to get free protection for your applications and to get access to all the features.
@@ -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