class Retl::Path

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.

@example

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)

Attributes

dependencies[R]
source[R]
steps[R]

Public Class Methods

new(parent=nil, &block) click to toggle source

Initializes a new Path

@param parent [Path] - a Path to inherit from

# File lib/retl/path.rb, line 48
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

Public Instance Methods

add_dependency(name, source) click to toggle source

Adds a depdency to the Path

@param name [Symbol] the name of the dependency

(should be a valid Ruby method)

@param source [#call] a callable object that will return the depdency

@return [void]

# File lib/retl/path.rb, line 176
def add_dependency(name, source)
  @dependencies[name] = source
end
add_fork(name, &block) click to toggle source

Adds an fork to the Path

Forks can be accessed via forks

@example

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

@param name [Symbol] the name of the fork

@return [void]

# File lib/retl/path.rb, line 140
def add_fork(name, &block)
  fork = Path.new(&block)
  @dependencies.each do |name, dependency|
    fork.add_dependency name, dependency
  end
  add_handler ForkHandler.new(name)
  @forks[name] = fork 
end
add_fork_builder(name, &block) click to toggle source

Adds a fork builder block

@param name [Symbol] the name of the fork to build @param &block [Block] the block that builds the fork

@return [Fork] the built fork

# File lib/retl/path.rb, line 164
def add_fork_builder(name, &block)
  @fork_builders[name] = block
  add_fork(name, &block)
end
add_handler(handler) click to toggle source
# File lib/retl/path.rb, line 94
def add_handler(handler)
  @steps << handler
end
add_step(step, handler: StepHandler) click to toggle source

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.

@param step [#call(data)] the step to take

@return [void]

# File lib/retl/path.rb, line 90
def add_step(step, handler: StepHandler)
  add_handler handler.new(step)
end
build(&block) click to toggle source

Builds a Path with the PathBuilder DSL

@return [void]

# File lib/retl/path.rb, line 65
def build(&block)
  PathBuilder.new(self, &block)
end
call(input, context=Context.new(self)) click to toggle source

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.

@param data [Hash] the data that will be transformed by the Path @param context [Context] the execution context for the transformation

@return [Array<Hash>] the transformed data

# File lib/retl/path.rb, line 110
def call(input, context=Context.new(self))
  @steps.reduce([input]) do |queue, handler|
    queue.each do |data|
      begin
        handler.push_in(data, context)
      rescue Exception => e
        raise StepExecutionError.new(
          input_data: input, 
          current_data: data, 
          step: handler
        )
      end
    end
    handler.output
  end
end
forks(name) click to toggle source

Gets a fork by name

@param name [Symbol] the name of the fork to get

@return [Path] the forked path

# File lib/retl/path.rb, line 154
def forks(name)
  @forks[name]
end
initialize_copy(source) click to toggle source

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.

# File lib/retl/path.rb, line 74
def initialize_copy(source)
  @steps         = source.steps.dup
  @forks         = {}
  @fork_builders = {}
end
transform(enumerable, options={}) click to toggle source

Executes the Path with data

@param [Enumerable] the data that will be processed by the Path @option options that will be passed to depends_on for the context

@return [Transformation] the Tranformation of the data by the Path

# File lib/retl/path.rb, line 186
def transform(enumerable, options={})
  Transformation.new(enumerable, self, options)
end
transform!(enumerable, options={}) click to toggle source
# File lib/retl/path.rb, line 190
def transform!(enumerable, options={})
  transform(enumerable, options).tap do |transformation|
    transformation.execution_strategy = ThreadedExecution
  end
end