In Files

Namespace

Class/Module Index [+]

Quicksearch

Ruote

Constants

DUMMY_WORKER

A helper for the worker method, it returns that dummy worker when there is no reference to the calling worker in the current thread’s local variables.

IDS
JAVA

Will be set to true if the Ruby runtime is JRuby

REGEX_IN_STRING
SUBS
VERSION
WIN

Will be set to true if the Ruby runtime is on Windows

Public Class Methods

camelize(s, first_up=false) click to toggle source

Our own quick camelize implementation (no need to require active support).

# File lib/ruote/util/misc.rb, line 240
def self.camelize(s, first_up=false)

  s = s.capitalize if first_up

  s.gsub(/(_.)/) { |x| x[1, 1].upcase }
end
comma_split(o) click to toggle source

Returns an array. If the argument is an array, return it as is. Else turns the argument into a string and “comma splits” it.

# File lib/ruote/util/misc.rb, line 199
def self.comma_split(o)

  o.is_a?(Array) ? o : o.to_s.split(/\s*,\s*/).collect { |e| e.strip }
end
compact_tree(tree) click to toggle source

Compacts

[ 'participant', { 'ref' => 'sam' }, [] ] # and
[ 'subprocess', { 'ref' => 'compute_prime' }, [] ]

into

[ 'sam', {}, [] ] # and
[ 'compute_prime', {}, [] ]

to simplify tree comparisons.

# File lib/ruote/util/tree.rb, line 73
def self.compact_tree(tree)

  tree = tree.dup

  if ] participant subprocess ].include?(tree[0])

    ref =
      tree[1].delete('ref') ||
      begin
        kv = tree[1].find { |k, v| v == nil }
        tree[1].delete(kv[0])
        kv[0]
      end

    tree[0] = ref

  else

    tree[2] = tree[2].collect { |t| compact_tree(t) }
  end

  tree
end
constantize(s) click to toggle source

(simpler than the one from active_support)

# File lib/ruote/util/misc.rb, line 124
def self.constantize(s)

  s.split('::').inject(Object) { |c, n| n == '' ? c : c.const_get(n) }
end
cron_string?(s) click to toggle source

Waiting for a better implementation of it in rufus-scheduler 2.0.4

# File lib/ruote/util/time.rb, line 91
def self.cron_string?(s)

  ss = s.split(' ')

  return false if ss.size < 5 || ss.size > 6
  return false if s.match(/\d{4}/)

  true
end
current_worker() click to toggle source

Warning, this is not equivalent to doing @context.worker, this method fetches the worker from the local thread variables.

# File lib/ruote/worker.rb, line 40
def self.current_worker

  Thread.current['ruote_worker'] || DUMMY_WORKER
end
decamelize(s) click to toggle source

Quick decamelize implementation.

# File lib/ruote/util/misc.rb, line 249
def self.decamelize(s)

  s.gsub(/(.)([A-Z])/, '\1_\2').downcase
end
decompose_tree(t, pos='0', h={}) click to toggle source

Used by some projects, used to be called from Ruote::ProcessStatus.

Given a tree

[ 'define', { 'name' => 'nada' }, [
  [ 'sequence', {}, [ [ 'alpha', {}, [] ], [ 'bravo', {}, [] ] ] ]
] ]

will output something like

{ '0' => [ 'define', { 'name' => 'nada' } ],
  '0_0' => [ 'sequence', {} ],
  '0_0_0' => [ 'alpha', {} ],
  '0_0_1' => [ 'bravo', {} ] },

An initial offset can be specifid with the ‘pos’ argument.

Don’t touch ‘h’, it’s an accumulator.

# File lib/ruote/util/tree.rb, line 116
def self.decompose_tree(t, pos='0', h={})

  h[pos] = t[0, 2]
  t[2].each_with_index { |c, i| decompose_tree(c, "#{pos}_#{i}", h) }
  h
end
deep_delete(h, key) click to toggle source

Given a hash and a key, deletes all the entries with that key, in child hashes too.

Note: this method is not related to the “dot notation” methods in this lookup.rb file.

example

h = { 'a' => 1, 'b' => { 'a' => 2 } }
Ruote.deep_delete(h, 'a')
  # => { 'b' => {} }
# File lib/ruote/util/deep.rb, line 45
def self.deep_delete(h, key)

  h.delete(key)

  h.each { |k, v| deep_delete(v, key) if v.is_a?(Hash) }
end
Also aliased as: delete_all
deep_merge!(target, source) click to toggle source

Inspired by the one found in ActiveSupport, though not strictly equivalent.

# File lib/ruote/merge.rb, line 116
def self.deep_merge!(target, source)

  target.merge!(source) do |k, o, n|
    o.is_a?(Hash) && n.is_a?(Hash) ? deep_merge!(o, n) : n
  end
end
deep_mutate(coll, key_or_keys, parent=nil, &block) click to toggle source

Dives into a nested structure of hashes and arrays to find match hash keys.

The method expects a block with 3 or 4 arguments.

3 arguments: collection, key and value 4 arguments: parent collection, collection, key and value

Warning: .deep_mutate forces hash keys to be strings. It’s a JSON world.

example

h = {
  'a' => 0,
  'b' => 1,
  'c' => { 'a' => 2, 'b' => { 'a' => 3 } },
  'd' => [ { 'a' => 0 }, { 'b' => 4 } ] }

Ruote.deep_mutate(h, 'a') do |coll, k, v|
  coll['a'] = 10
end

h # =>
  { 'a' => 10,
    'b' => 1,
    'c' => { 'a' => 10, 'b' => { 'a' => 10 } },
    'd' => [ { 'a' => 10 }, { 'b' => 4 } ] }

variations

Instead of a single key, it’s OK to pass an array of keys:

Ruote.deep_mutate(a, [ 'a', 'b' ]) do |coll, k, v|
  # ...
end

Regular expressions are made to match:

Ruote.deep_mutate(a, [ 'a', /^a\./ ]) do |coll, k, v|
  # ...
end

A single regular expression is OK:

Ruote.deep_mutate(a, /^user\./) do |coll, k, v|
  # ...
end
# File lib/ruote/util/deep.rb, line 103
def self.deep_mutate(coll, key_or_keys, parent=nil, &block)

  keys = key_or_keys.is_a?(Array) ? key_or_keys : [ key_or_keys ]

  if coll.is_a?(Hash)

    coll.dup.each do |k, v|

      # ensure that all keys are strings

      unless k.is_a?(String)

        coll.delete(k)
        k = k.to_s
        coll[k] = v
      end

      # call the mutation blocks for each match

      if keys.find { |kk| kk.is_a?(Regexp) ? kk.match(k) : kk == k }

        if block.arity > 3
          block.call(parent, coll, k, v)
        else
          block.call(coll, k, v)
        end
      end

      if v.is_a?(Array) || v.is_a?(Hash)

        deep_mutate(v, keys, coll, &block)
      end
    end

  elsif coll.is_a?(Array)

    coll.each { |e| deep_mutate(e, keys, coll, &block) }

  #else # nothing
  end
end
define(*attributes, &block) click to toggle source

Not really a reader, more an AST builder.

pdef = Ruote.define :name => 'take_out_garbage' do
  sequence do
    take_out_regular_garbage
    take_out_glass
    take_out_paper
  end
end

engine.launch(pdef)
# File lib/ruote/reader/ruby_dsl.rb, line 43
def self.define(*attributes, &block)

  RubyDsl.create_branch('define', attributes, &block)
end
delete_all(h, key) click to toggle source
Alias for: deep_delete
do_filter(filter, hash, options) click to toggle source

Used by Ruote.filter

# File lib/ruote/util/filter.rb, line 96
def self.do_filter(filter, hash, options)

  hash = Rufus::Json.dup(hash)

  hash['~'] = Rufus::Json.dup(hash)
  hash['~~'] = Rufus::Json.dup(options[:double_tilde] || hash)
    # the 'originals'

  deviations = filter.collect { |rule|
    RuleSession.new(hash, rule).run
  }.flatten(1)

  hash.delete('~')
  hash.delete('~~')
  hash.delete('~~~')
    # remove the 'originals'

  if deviations.empty?
    hash
  elsif options[:no_raise]
    deviations
  else
    raise ValidationError.new(deviations)
  end
end
extract_child_id(o) click to toggle source

Given something that might be a fei, extract the child_id (the last portion of the expid in the fei).

# File lib/ruote/extract.rb, line 84
def self.extract_child_id(o)

  fei = Ruote::FlowExpressionId.extract(o)

  fei ? fei.child_id : nil
end
extract_fei(o) click to toggle source

Given something, tries to return the fei (Ruote::FlowExpressionId) in it.

# File lib/ruote/extract.rb, line 76
def self.extract_fei(o)

  Ruote::FlowExpressionId.extract(o)
end
extract_fexp(context, fei_or_fexp) click to toggle source

Given a context and a fei (FlowExpressionId or Hash) or a flow expression (Ruote::Exp::FlowExpression or Hash) return the desired Ruote::Exp::FlowExpression instance.

# File lib/ruote/extract.rb, line 108
def self.extract_fexp(context, fei_or_fexp)

  return fei_or_fexp if fei_or_fexp.is_a?(Ruote::Exp::FlowExpression)

  fei = case fei_or_fexp
    when Ruote::FlowExpressionId then fei_or_fexp
    when Hash, String then extract_fei(fei_or_fexp)
    else nil
  end

  raise ArgumentError.new(
    "failed to extract flow expression out of #{fei_or_fexp.class} instance"
  ) unless fei

  Ruote::Exp::FlowExpression.fetch(context, fei)
end
extract_id(o) click to toggle source

Will do its best to return a wfid (String) or a fei (Hash instance) extract from the given o argument.

# File lib/ruote/extract.rb, line 67
def self.extract_id(o)

  return o if o.is_a?(String) and o.index('!').nil? # wfid

  Ruote::FlowExpressionId.extract_h(o)
end
extract_wfid(o) click to toggle source

Given an object, will return the wfid (workflow instance id) nested into it (or nil if it can’t find or doesn’t know how to find).

The wfid is a String instance.

# File lib/ruote/extract.rb, line 96
def self.extract_wfid(o)

  return o.strip == '' ? nil : o if o.is_a?(String)
  return o.wfid if o.respond_to?(:wfid)
  return o['wfid'] || o.fetch('fei', {})['wfid'] if o.respond_to?(:[])
  nil
end
filter(filter, hash, options={}) click to toggle source

Given a filter (a list of rules) and a hash (probably workitem fields) performs the validations / transformations dictated by the rules.

See the Ruote::Exp::FilterExpression for more information.

# File lib/ruote/util/filter.rb, line 48
def self.filter(filter, hash, options={})

  raise ArgumentError.new(
    "not a filter : #{filter}"
  ) unless filter.is_a?(Array)

  filters = or_split(filter)

  result = nil

  filters.each do |fl|

    result = begin
      do_filter(fl, hash, options)
    rescue ValidationError => err
      err
    end

    return result if result.is_a?(Hash)
      # success
  end

  raise(result) if result.is_a?(ValidationError)

  result
end
fulldup(object) click to toggle source

Deep object duplication

# File lib/ruote/util/misc.rb, line 50
def self.fulldup(object)

  return object.fulldup if object.respond_to?(:fulldup)
    # trusting client objects providing a fulldup() implementation
    # Tomaso Tosolini 2007.12.11

  begin
    return Marshal.load(Marshal.dump(object))
      # as soon as possible try to use that Marshal technique
      # it's quite fast
  rescue TypeError => te
  end

  #if object.is_a?(REXML::Element)
  #  d = REXML::Document.new object.to_s
  #  return d if object.kind_of?(REXML::Document)
  #  return d.root
  #end
    # avoiding "TypeError: singleton can't be dumped"

  o = object.class.allocate

  # some kind of collection ?

  if object.is_a?(Array)
    object.each { |i| o << fulldup(i) }
  elsif object.is_a?(Hash)
    object.each { |k, v| o[fulldup(k)] = fulldup(v) }
  end

  # duplicate the attributes of the object

  object.instance_variables.each do |v|
    value = object.instance_variable_get(v)
    value = fulldup(value)
    begin
      o.instance_variable_set(v, value)
    rescue
      # ignore, must be readonly
    end
  end

  o
end
generate_subid(salt) click to toggle source

This function is used to generate the subids. Each flow expression receives such an id (it’s useful for cursors, loops and forgotten branches).

# File lib/ruote/fei.rb, line 40
def self.generate_subid(salt)

  Digest::MD5.hexdigest(
    "#{rand}-#{salt}-#{$$}-#{Thread.current.object_id}#{Time.now.to_f}")
end
has_key?(collection, key) click to toggle source

h = { ‘a’ => { ‘b’ => [ 1, 3, 4 ] } }

p Ruote.lookup(h, ‘a.b.1’) # => true

# File lib/ruote/util/lookup.rb, line 56
def self.has_key?(collection, key)

  return collection if key == '.'

  key, rest = pop_key(key)

  return has_key?(fetch(collection, key), rest) if rest.any?

  if collection.respond_to?(:has_key?)
    collection.has_key?(key)
  elsif collection.respond_to?(:[])
    key.to_i < collection.size
  else
    false
  end
end
insp(o, opts={}) click to toggle source

A bit like inspect but produces a tighter output (ambiguous to machines).

# File lib/ruote/util/misc.rb, line 206
def self.insp(o, opts={})

  case o
    when nil
      'nil'
    when Hash
      trim = opts[:trim] || []
      '{' +
      o.reject { |k, v|
        v.nil? && trim.include?(k.to_s)
      }.collect { |k, v|
        "#{k}: #{insp(v)}"
      }.join(', ') +
      '}'
    when Array
      '[' + o.collect { |e| insp(e) }.join(', ') + ']'
    when String
      o.match(/\s/) ? o.inspect : o
    else
      o.inspect
  end
end
is_a_fei?(o) click to toggle source

Returns true if the h is a representation of a FlowExpressionId instance.

# File lib/ruote/extract.rb, line 56
def self.is_a_fei?(o)

  return true if o.is_a?(Ruote::FlowExpressionId)
  return false unless o.is_a?(Hash)

  (o.keys - SUBS).sort == IDS
end
is_definition_tree?(arg) click to toggle source

Returns true if the argument is a process definition tree (whose root is ‘define’, ‘process_definition’ or ‘workflow_definition’.

# File lib/ruote/util/subprocess.rb, line 62
def self.is_definition_tree?(arg)

  Ruote::Exp::DefineExpression.is_definition?(arg) && is_tree?(arg)
end
is_pos_tree?(arg) click to toggle source

Mainly used by Ruote.lookup_subprocess, returns true if the argument is is an array [ position, tree ].

# File lib/ruote/util/subprocess.rb, line 80
def self.is_pos_tree?(arg)

  arg.is_a?(Array) &&
  arg.size == 2 &&
  arg[0].is_a?(String) &&
  is_tree?(arg[1])
end
is_tree?(arg) click to toggle source

Returns true if the given argument is a process definition tree (its root doesn’t need to be ‘define’ or ‘process_definition’ though).

# File lib/ruote/util/subprocess.rb, line 70
def self.is_tree?(arg)

  arg.is_a?(Array) && arg.size == 3 &&
  arg[0].is_a?(String) && arg[1].is_a?(Hash) && arg[2].is_a?(Array) &&
  (arg.last.empty? || arg.last.find { |e| ! is_tree?(e) }.nil?)
end
is_uri?(s) click to toggle source

Returns true if the string seems to correpond to a URI

TODO : wouldn’t it be better to simply use URI.parse() ?

# File lib/ruote/util/misc.rb, line 99
def self.is_uri?(s)

  s && (s.index('/') || s.match(/\.[^ ]+$/))
end
keys_to_s(h) click to toggle source

Makes sure all they keys in the given hash are turned into strings in the resulting hash.

# File lib/ruote/util/misc.rb, line 132
def self.keys_to_s(h)

  h.remap { |(k, v), h| h[k.to_s] = v }
end
keys_to_sym(h) click to toggle source

Makes sure all they keys in the given hash are turned into symbols in the resulting hash.

Mostly used in ruote-amqp.

# File lib/ruote/util/misc.rb, line 142
def self.keys_to_sym(h)

  h.remap { |(k, v), h| h[k.to_sym] = v }
end
local_ip() click to toggle source

From coderrr.wordpress.com/2008/05/28/get-your-local-ip-address/

Returns the (one of the) local IP address.

# File lib/ruote/util/misc.rb, line 166
def self.local_ip

  orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true
    # turn off reverse DNS resolution temporarily

  UDPSocket.open do |s|
    s.connect('64.233.187.99', 1)
    s.addr.last
  end

rescue

  nil

ensure
  Socket.do_not_reverse_lookup = orig
end
lookup(collection, key, container_lookup=false) click to toggle source

h = { ‘a’ => { ‘b’ => [ 1, 3, 4 ] } }

p Ruote.lookup(h, ‘a.b.1’) # => 3

# File lib/ruote/util/lookup.rb, line 37
def self.lookup(collection, key, container_lookup=false)

  return collection if key == '.'

  key, rest = pop_key(key)
  value = fetch(collection, key)

  return [ key, collection ] if container_lookup && rest.size == 0
  return [ rest.first, value ] if container_lookup && rest.size == 1
  return value if rest.size == 0
  return nil if value == nil

  lookup(value, rest, container_lookup)
end
lookup_subprocess(fexp, ref) click to toggle source

This method is used by the ‘subprocess’ expression and by the EngineParticipant.

# File lib/ruote/util/subprocess.rb, line 35
def self.lookup_subprocess(fexp, ref)

  val = fexp.lookup_variable(ref)

  # a classical subprocess stored in a variable ?

  return [ '0', val ] if is_tree?(val)
  return val if is_pos_tree?(val)

  # maybe subprocess :ref => 'uri'

  subtree = fexp.context.reader.read(ref) rescue nil

  if subtree && is_definition_tree?(subtree)
    _, subtree = Ruote::Exp::DefineExpression.reorganize(subtree)
  end

  return [ '0', subtree ] if is_tree?(subtree)

  # no luck ...

  raise "no subprocess named '#{ref}' found"
end
merge_workitem(index, target, source, merge_type) click to toggle source

Merge workitem ‘source’ into workitem ‘target’.

If type is ‘override’, the source will prevail and be returned.

If type is ‘mix’, the source fields will be merged into the target fields.

If type is ‘isolate’, the source fields will be placed in a separte field in the target workitem. The name of this field is the child_id of the source workitem (a string from ‘0’ to ‘99999’ and beyond)

The ‘concat’ type merges hashes and concats arrays. The ‘union’ type behaves much like ‘concat’, but it makes sure to remove duplicates.

Warning: ‘union’ will remove duplicates that were present before the merge.

# File lib/ruote/merge.rb, line 48
def self.merge_workitem(index, target, source, merge_type)

  if merge_type == 'override'

    return source
  end

  if target == nil

    case merge_type

      when 'stack'

        source['fields'] = { 'stack' => [ source['fields'] ] }

      when 'isolate'

        source['fields'] = { (index || 0).to_s => source['fields'] }

      #when 'mix'
         # do nothing
      #when 'union', 'concat'
         # do nothing
    end

    return source
  end

  # else, regular merge

  case merge_type

    when 'mix'

      target['fields'].merge!(source['fields'])

    when 'stack'

      target['fields']['stack'] << source['fields']

    when 'isolate'

      index ||= target['fields'].keys.select { |k| k.match(/^\d+$/) }.size
      target['fields'][index.to_s] = source['fields']

    when 'union', 'concat', 'deep'

      source['fields'].each do |k, sv|

        tv = target['fields'][k]

        if sv.is_a?(Array) and tv.is_a?(Array)
          tv.concat(sv)
          tv.uniq! if merge_type == 'union'
        elsif sv.is_a?(Hash) and tv.is_a?(Hash)
          merge_type == 'deep' ? deep_merge!(tv, sv) : tv.merge!(sv)
        else
          target['fields'][k] = sv
        end
      end
  end

  target
end
narrow_to_number(o) click to toggle source

Tries to return an Integer or a Float from the given input. Returns

# File lib/ruote/util/misc.rb, line 113
def self.narrow_to_number(o)

  return o if [ Fixnum, Bignum, Float ].include?(o.class)

  s = o.to_s

  (s.index('.') ? Float(s) : Integer(s)) rescue nil
end
neutralize(s) click to toggle source

Returns a neutralized version of s, suitable as a filename.

# File lib/ruote/util/misc.rb, line 106
def self.neutralize(s)

  s.to_s.strip.gsub(/[ \/:;\*\\\+\?]/, '_')
end
now_to_utc_s() click to toggle source

Returns a parseable representation of the UTC time now.

like “2009/11/23 11:11:50.947109 UTC”

# File lib/ruote/util/time.rb, line 57
def self.now_to_utc_s

  time_to_utc_s(Time.now)
end
or_split(filter) click to toggle source

Used by Ruote.filter

# File lib/ruote/util/filter.rb, line 77
def self.or_split(filter)

  return filter if filter.first.is_a?(Array)
  return [ filter ] if filter.empty? or ( ! filter.include?('or'))

  # [ {}, 'or', {}, {}, 'or', {} ]

  filter.inject([ [] ]) do |result, fl|
    if fl.is_a?(Hash)
      result.last << fl
    else
      result << []
    end
    result
  end
end
p_caller(*msg) click to toggle source

Prints the current call stack to stdout

# File lib/ruote/util/misc.rb, line 40
def self.p_caller(*msg)

  puts
  puts "  == #{msg.inspect} =="
  caller(1).each { |l| puts "  #{l}" }
  puts
end
parse_ruby(ruby_string) click to toggle source

Attempts to parse a string of Ruby code (and return the AST).

# File lib/ruote/util/misc.rb, line 186
def self.parse_ruby(ruby_string)

  Rufus::TreeChecker.parse(ruby_string)

rescue NoMethodError

  raise NoMethodError.new(
    "/!\\ please upgrade your rufus-treechecker gem /!\\")
end
participant_send(participant, methods, arguments) click to toggle source

Given a participant, a method name or an array of method names and a hash of arguments, will do its best to set the instance variables corresponding to the arguments (if possible) and to call the method with the right number of arguments…

Made it a Ruote module method so that RevParticipant might use it independently.

If the arguments hash contains a value keyed :default, that value is returned when none of the methods is responded to by the participant. Else if :default is not set or is set to nil, a NoMethodError.

# File lib/ruote/svc/dispatch_pool.rb, line 193
def self.participant_send(participant, methods, arguments)

  default = arguments.delete(:default)

  # set instance variables if possible

  arguments.each do |key, value|
    setter = "#{key}="
    participant.send(setter, value) if participant.respond_to?(setter)
  end

  # call the method, with the right arity

  Array(methods).each do |method|

    next unless participant.respond_to?(method)

    return participant.send(method) if participant.method(method).arity == 0

    args = arguments.keys.sort.collect { |k| arguments[k] }
      # luckily, our arg keys are in the alphabetical order (fei, flavour)

    return participant.send(method, *args)
  end

  return default unless default == nil

  raise NoMethodError.new(
    "undefined method `#{methods.first}' for #{participant.class}")
end
pps(o, w=79) click to toggle source
# File lib/ruote/util/misc.rb, line 229
def self.pps(o, w=79)

  PP.pp(o, StringIO.new, w).string
end
process_definition(*attributes, &block) click to toggle source

Same as Ruote.define()

pdef = Ruote.process_definition :name => 'take_out_garbage' do
  sequence do
    take_out_regular_garbage
    take_out_paper
  end
end

engine.launch(pdef)
# File lib/ruote/reader/ruby_dsl.rb, line 59
def self.process_definition(*attributes, &block)

  define(*attributes, &block)
end
recompose_tree(h, pos='0') click to toggle source

Used by some projects, used to be called from Ruote::ProcessStatus.

Given a decomposed tree like

{ '0' => [ 'define', { 'name' => 'nada' } ],
  '0_0' => [ 'sequence', {} ],
  '0_0_0' => [ 'alpha', {} ],
  '0_0_1' => [ 'bravo', {} ] },

will recompose it to

[ 'define', { 'name' => 'nada' }, [
  [ 'sequence', {}, [ [ 'alpha', {}, [] ], [ 'bravo', {}, [] ] ] ]
] ]

A starting point in the recomposition can be given with the ‘pos’ argument.

# File lib/ruote/util/tree.rb, line 140
def self.recompose_tree(h, pos='0')

  t = h[pos]

  return nil unless t

  t << []
  i = 0

  loop do
    tt = recompose_tree(h, "#{pos}_#{i}")
    break unless tt
    t.last << tt
    i = i + 1
  end

  t
end
regex_or_s(s) click to toggle source

regex_or_s("/nada/") #==> /nada/ regex_or_s("nada") #==> "nada" regex_or_s(/nada/) #==> /nada/

# File lib/ruote/util/misc.rb, line 153
def self.regex_or_s(s)

  if s.is_a?(String) && m = REGEX_IN_STRING.match(s)
    Regexp.new(m[1])
  else
    s
  end
end
s_to_at(s) click to toggle source

Turns a date or a duration to a Time object pointing AT a point in time…

(my prose is weak)

# File lib/ruote/util/time.rb, line 66
def self.s_to_at(s)

  at =
    if s.match(/[ :]/)
      #
      # date

      DateTime.parse(s)

    else
      #
      # duration

      Time.now.utc.to_f + Rufus.parse_time_string(s)
    end

  case at
    when DateTime then at.to_time.utc
    when Float then Time.at(at).utc
    else at
  end
end
schedule_to_h(sched) click to toggle source

Refines a schedule as found in the ruote storage into something a bit easier to present.

# File lib/ruote/dashboard.rb, line 1379
def self.schedule_to_h(sched)

  h = sched.dup

  class << h; attr_accessor :h; end
  h.h = sched
    #
    # for the sake of ProcessStatus#to_h

  h.delete('_rev')
  h.delete('type')
  msg = h.delete('msg')
  owner = h.delete('owner')

  h['wfid'] = owner['wfid']
  h['action'] = msg['action']
  h['type'] = msg['flavour']
  h['owner'] = Ruote::FlowExpressionId.new(owner)

  h['target'] = Ruote::FlowExpressionId.new(msg['fei']) if msg['fei']

  h
end
set(collection, key, value) click to toggle source

h = { ‘customer’ => { ‘name’ => ‘alpha’ } }

Ruote.set(h, 'customer.name', 'bravo')

h #=> { ‘customer’ => { ‘name’ => ‘bravo’ } }

# File lib/ruote/util/lookup.rb, line 79
def self.set(collection, key, value)

  k, c = lookup(collection, key, true)

  if c
    k = k.to_i if c.is_a?(Array)
    c[k] = value
  else
    collection[key] = value
  end
end
sid(fei) click to toggle source

A shorter shortcut for

Ruote::FlowExpressionId.to_storage_id(fei)
# File lib/ruote/extract.rb, line 46
def self.sid(fei)

  Ruote::FlowExpressionId.to_storage_id(fei)
end
time_to_utc_s(t) click to toggle source

Produces the UTC string representation of a Time

like “2009/11/23 11:11:50.947109 UTC”

# File lib/ruote/util/time.rb, line 48
def self.time_to_utc_s(t)

  "#{t.utc.strftime('%Y-%m-%d %H:%M:%S')}.#{sprintf('%06d', t.usec)} UTC"
end
to_storage_id(fei) click to toggle source

A shortcut for

Ruote::FlowExpressionId.to_storage_id(fei)
# File lib/ruote/extract.rb, line 37
def self.to_storage_id(fei)

  Ruote::FlowExpressionId.to_storage_id(fei)
end
to_tree(&block) click to toggle source

Similar in purpose to Ruote.define and Ruote.process_definition but instead of returning a [process] definition, returns the tree.

tree = Ruote.process_definition :name => 'take_out_garbage' do
  sequence do
    take_out_regular_garbage
    take_out_paper
  end
end

p tree
  # => [ 'sequence', {}, [ [ 'take_out_regular_garbage', {}, [] ], [ 'take_out_paper', {}, [] ] ] ],

This is useful when modifying a process instance via methods like re_apply :

engine.re_apply(
  fei,
  :tree => Ruote.to_tree {
    sequence do
      participant 'alfred'
      participant 'bob'
    end
  })
    #
    # cancels the segment of process at fei and replaces it with
    # a simple alfred-bob sequence.
# File lib/ruote/reader/ruby_dsl.rb, line 91
def self.to_tree(&block)

  RubyDsl.create_branch('x', {}, &block).last.first
end
Also aliased as: tree
tree(&block) click to toggle source
Alias for: to_tree
tree_to_dot(tree, name='ruote process definition') click to toggle source

Turns a process definition tree to a graphviz dot representation.

www.graphviz.org

# File lib/ruote/tree_dot.rb, line 32
def self.tree_to_dot(tree, name='ruote process definition')

  s = "digraph \"#{name}\" {\n"
  s << branch_to_dot('0', tree).join("\n")
  s << "\n}\n"
end
tree_to_s(tree, expid='0') click to toggle source

Turning a tree into a numbered string view

require 'ruote/util/tree'
require 'ruote/reader/ruby_dsl'

pdef = Ruote.process_definition :name => 'def0' do
  sequence do
    alpha
    bravo
  end
end

p pdef
  # => ["define", {"name"=>"def0"}, [
  #      ["sequence", {}, [
  #        ["alpha", {}, []],
  #        ["bravo", {}, []]]]]]

puts Ruote.tree_to_s(pdef)
  # =>
  #    0  define {"name"=>"def0"}
  #      0_0  sequence {}
  #        0_0_0  alpha {}
  #        0_0_1  bravo {}
# File lib/ruote/util/tree.rb, line 53
def self.tree_to_s(tree, expid='0')

  d = expid.split('_').size - 1
  s = "#{' ' * d * 2}#{expid}  #{tree[0]} #{tree[1].inspect}\n"
  tree[2].each_with_index { |t, i| s << tree_to_s(t, "#{expid}_#{i}") }
  s
end
unset(collection, key) click to toggle source

h = { ‘customer’ => { ‘name’ => ‘alpha’, ‘rank’ => ‘1st’ } } r = Ruote.unset(h, ‘customer.rank’)

h # => { ‘customer’ => { ‘name’ => ‘alpha’ } } r # => ‘1st’

# File lib/ruote/util/lookup.rb, line 97
def self.unset(collection, key)

  k, c = lookup(collection, key, true)

  if c.nil?
    collection.delete(key)
  elsif c.is_a?(Array)
    c.delete_at(Integer(k)) rescue nil
  elsif c.is_a?(Hash)
    c.delete(k)
  else
    nil
  end
end

Protected Class Methods

branch_to_dot(expid, exp) click to toggle source
# File lib/ruote/tree_dot.rb, line 41
def self.branch_to_dot(expid, exp)

  [
    "  \"#{expid}\" "+
    "[ label = \"#{exp[0]} #{exp[1].inspect.gsub("\"", "'")}\" ];"
  ] +
  children_to_dot(expid, exp)
end
children_to_dot(expid, exp) click to toggle source
# File lib/ruote/tree_dot.rb, line 50
def self.children_to_dot(expid, exp)

  exp_name = exp[0]
  child_count = exp[2].size

  i = -1

  a = exp[2].collect do |child|
    i += 1
    branch_to_dot("#{expid}_#{i}", child)
  end

  if child_count > 0 # there are children

    if ] concurrence if ].include?(exp_name)

      (0..child_count - 1).each do |i|
        a << "  \"#{expid}\" -> \"#{expid}_#{i}\";"
        a << "  \"#{expid}_#{i}\" -> \"#{expid}\";"
      end

    else

      a << "  \"#{expid}\" -> \"#{expid}_0\";"
      a << "  \"#{expid}_#{child_count -1}\" -> \"#{expid}\";"

      (0..child_count - 2).each do |i|
        a << "  \"#{expid}_#{i}\" -> \"#{expid}_#{i + 1}\";"
      end
    end
  end

  a
end
fetch(collection, key) click to toggle source

Given a collection and a key returns the corresponding value

Ruote.fetch([ 12, 13, 24 ], 1) # => 13
Ruote.fetch({ '1' => 13 }, 1) # => 13
Ruote.fetch({ 1 => 13 }, 1) # => 13
# File lib/ruote/util/lookup.rb, line 141
def self.fetch(collection, key)

  value = (collection[key] rescue nil)

  if value == nil and key.is_a?(Fixnum)
    (collection[key.to_s] rescue nil)
  else
    value
  end
end
narrow_key(key) click to toggle source

If the key holds an integer returns it, else return the key as is.

# File lib/ruote/util/lookup.rb, line 130
def self.narrow_key(key)

  key.match(/^-?\d+$/) ? key.to_i : key
end
pop_key(key) click to toggle source

Pops the first key in a path key.

Ruote.pop_key('a.b.c') # => 'a'
Ruote.pop_key('1.2.3') # => 1

(note the narrowing to an int that happens)

# File lib/ruote/util/lookup.rb, line 121
def self.pop_key(key)

  ks = key.is_a?(String) ? key.split('.') : key

  [ narrow_key(ks.first), ks[1..-1] ]
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.