Class: Retl::Path

Inherits:
Object
  • Object
show all
Defined in:
lib/retl/path.rb

Overview

A Path is a blueprint for transforming data

A Path is a sequence of steps that are executed on data in order to transform it.

Paths can be built with a block using the API defined in the #PathBuilder.

Steps are added to the Path with the #add_step method.

A Path can act on a single piece of data with the #call method.

A Path can transform a list of data with the #transform method.

Examples:

path = Retl::Path.new do 
  step do |data|
    data[:something] = "some value"
    data
  end

  calculate(:something_else) do 
    "some other value"
  end

  transform do |data|
    data[:something_together] = data[:something] + data[:something_else]
  end
end

path.transform(data)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(parent = nil, &block) ⇒ Path

Initializes a new Path

Parameters:

  • parent (Path) (defaults to: nil)
    • a Path to inherit from



47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/retl/path.rb', line 47

def initialize(parent=nil, &block)
  @steps         = []
  @dependencies  = {}
  @forks         = {}
  @fork_builders = {}

  if parent
    @dependencies = parent.dependencies.dup
    add_step parent.dup, handler: ExplodeHandler
  end

  build(&block) if block
end

Instance Attribute Details

#dependenciesObject (readonly)

Returns the value of attribute dependencies.



42
43
44
# File 'lib/retl/path.rb', line 42

def dependencies
  @dependencies
end

#sourceObject (readonly)

Returns the value of attribute source.



42
43
44
# File 'lib/retl/path.rb', line 42

def source
  @source
end

#stepsObject (readonly)

Returns the value of attribute steps.



42
43
44
# File 'lib/retl/path.rb', line 42

def steps
  @steps
end

Instance Method Details

#add_dependency(name, source) ⇒ void

This method returns an undefined value.

Adds a depdency to the Path

Parameters:

  • name (Symbol)

    the name of the dependency (should be a valid Ruby method)

  • source (#call)

    a callable object that will return the depdency



164
165
166
# File 'lib/retl/path.rb', line 164

def add_dependency(name, source)
  @dependencies[name] = source
end

#add_fork(name, &block) ⇒ void

This method returns an undefined value.

Adds an fork to the Path

Forks can be accessed via #forks

Examples:

path.add_fork(:river) do 
  filter { |data| data[:is_wet] }
end
path.forks(:river)

Parameters:

  • name (Symbol)

    the name of the fork



131
132
133
134
135
# File 'lib/retl/path.rb', line 131

def add_fork(name, &block)
  fork = Path.new(&block)
  add_handler ForkHandler.new(name)
  @forks[name] = fork 
end

#add_fork_builder(name, &block) ⇒ Fork

Adds a fork builder block

Parameters:

  • name (Symbol)

    the name of the fork to build

  • &block (Block)

    the block that builds the fork

Returns:

  • (Fork)

    the built fork



152
153
154
155
# File 'lib/retl/path.rb', line 152

def add_fork_builder(name, &block)
  @fork_builders[name] = block
  add_fork(name, &block)
end

#add_handler(handler) ⇒ Object



93
94
95
# File 'lib/retl/path.rb', line 93

def add_handler(handler)
  @steps << handler
end

#add_step(step, handler: StepHandler) ⇒ void

This method returns an undefined value.

Adds a step to the Path

A step is called with data and is expected to return complete, modified data.

Steps are executed in the sequence they are added.

Parameters:

  • step (#call(data))

    the step to take



89
90
91
# File 'lib/retl/path.rb', line 89

def add_step(step, handler: StepHandler)
  add_handler handler.new(step)
end

#build(&block) ⇒ void

This method returns an undefined value.

Builds a Path with the PathBuilder DSL



64
65
66
# File 'lib/retl/path.rb', line 64

def build(&block)
  PathBuilder.new(self, &block)
end

#call(data, context = Context.new(self)) ⇒ Array<Hash>

Execuutes the Path with the given data

Currently the DSL mostly supports Hash based data, so this expects a Hash.

Since a piece of data can now be exploded, this method will always return an Array.

Parameters:

  • data (Hash)

    the data that will be transformed by the Path

  • context (Context) (defaults to: Context.new(self))

    the execution context for the transformation

Returns:

  • (Array<Hash>)

    the transformed data



109
110
111
112
113
114
115
116
# File 'lib/retl/path.rb', line 109

def call(data, context=Context.new(self))
  @steps.reduce([data]) do |queue, handler|
    queue.each do |data|
      handler.push_in(data, context)
    end
    handler.output
  end
end

#forks(name) ⇒ Path

Gets a fork by name

Parameters:

  • name (Symbol)

    the name of the fork to get

Returns:

  • (Path)

    the forked path



142
143
144
# File 'lib/retl/path.rb', line 142

def forks(name)
  @forks[name]
end

#initialize_copy(source) ⇒ Object

Initializer when copying a Path

When a Path is copied, a copy of the Path’s steps need to be copied as well. That was if additional steps are added to the original Path they won’t be part of the copied Path.



73
74
75
76
77
# File 'lib/retl/path.rb', line 73

def initialize_copy(source)
  @steps         = source.steps.dup
  @forks         = {}
  @fork_builders = {}
end

#transform(enumerable, options = {}) ⇒ Transformation

Executes the Path with data

Parameters:

  • the (Enumerable)

    data that will be processed by the Path

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • that (Object)

    will be passed to #depends_on for the context

Returns:



174
175
176
# File 'lib/retl/path.rb', line 174

def transform(enumerable, options={})
  Transformation.new(enumerable, self, options)
end