Class | Ruote::Exp::IteratorExpression |
In: |
lib/ruote/exp/fe_iterator.rb
|
Parent: | CommandedExpression |
Iterating on a list of values
pdef = Ruote.process_definition :name => 'test' do iterator :on_val => 'alice, bob, charly', :to_var => 'v' do participant '${v:v}' end end
This expression expects at list an ‘on’ attribute, which can be :on, :on_val, :on_value for a value (usually a comma separated list), :on_v, :on_var, :on_variable for a list contained in the designated variable and :on_f, :on_fld, :on_field for a list contained in the designated workitem field.
The ‘on’ attribute is used to instruct the expression on which list/array it should iterate.
The ‘to’ attribute takes two forms, :to_v, :to_var, :to_variable or :to_f, :to_fld, :to_field. Finally, you can write :to => ‘field_name’, :to => ‘f:field_name’ or :to => ‘v:variable_name’.
The ‘to’ attribute instructs the iterator into which variable or field it should place the current value (the value being iterated over).
If there is no ‘to’ specified, the current value is placed in the variable named ‘i’.
The variables ‘ii’ contains the index (from 0 to …) of the current value (think Ruby‘s each_with_index).
The ‘on’ attribute can be replaced by a :time or a :branches attribute.
pdef = Ruote.process_definition :name => 'test' do iterator :times => '3' do participant 'accounting' end end
will be equivalent to
pdef = Ruote.process_definition :name => 'test' do sequence do participant 'accounting' participant 'accounting' participant 'accounting' end end
Starting with ruote 2.3.0, the iterator doesn‘t create a new scope for its variables, it uses the current scope.
The old behaviour can be obtained by setting :scope => true, as in:
iterator :on => [ 1, 2, 3 ], :to_v => 'x', :scope => true do # ... end
A corollary: by default, the variables set by the iterator or within it stick in the current scope…
Iterating over a workitem field:
pdef = Ruote.process_definition :name => 'test' do iterator :on_field => 'customers', :to_f => 'customer' participant '${f:customer}' end end
It‘s equivalent to:
pdef = Ruote.process_definition :name => 'test' do iterator :on => '$f:customers', :to_f => 'customer' participant '${f:customer}' end end
"$f:customers" yields the actual array, whereas "${f:customers}" yields the string representation of the array.
The ‘iterator’ expression understands a certain the following commands :
pdef = Ruote.process_definition :name => ‘test’ do
iterator :times => '3' sequence do participant 'accounting', :review => '${v:i}' rewind :if => '${f:redo_everything} == true' end end
end
It‘s OK to issue a command to the iterator from a participant via the workitem.
pdef = Ruote.process_definition do iterator :times => 10 sequence do participant 'accounting' participant 'adjust' end end end
where
class Adjust include Ruote::LocalParticipant def consume(workitem) workitem.command = 'break' if workitem.fields['amount'] > 10_000 reply_to_engine(workitem) end def cancel(fei, flavour) end end
A completely stupid example… The adjust participant will make the loop break if the amount reaches 10_000 (euros?).
An iterator can be tagged (with the :tag attribute) and directly referenced from a break/rewind/continue/skip/jump command.
It‘s very useful when iterators (and cursors/loops) are nested within each other or when one has to act on an iterator from outside of it.
concurrence do iterator :on => 'alpha, bravo, charly', :tag => 'review' do participant '${v:i}' end # meanwhile ... sequence do participant 'main control program' _break :ref => 'review', :if => '${f:cancel_review} == yes' end end
in this example, the participant ‘main control program’ may cancel the review.
iterator :on => 'c1, c2, c3', :to_f => 'client', :tag => 'main' do cursor do participant :ref => '${f:client}' _break :ref => 'main', :if => '${f:cancel_everything}' participant :ref => 'salesclerk' participant :ref => 'salesclerk' end end
in this weird process, if one customer says "cancel everything" (set the workitem field "cancel_everything" to true), then the whole iterator gets ‘broken’ out of.