thbar / kiba

Data processing & ETL framework for Ruby
https://www.kiba-etl.org
Other
1.75k stars 87 forks source link

Unable to yield inside transform block #91

Closed glaucocustodio closed 4 years ago

glaucocustodio commented 4 years ago

The following code fails with etl.rb:X:in block (3 levels) in setup: no block given (yield) (LocalJumpError)

# etl.rb
module ETL
  module_function

  def setup(config = {})
    Kiba.parse do
      # ... input

      transform do |row|
        2.times do |i|
          yield({ foo: i })
        end
      end

      # ... output
    end
  end
end

This works:

# etl.rb
class ExplodingTransform
  def process(row)
    2.times do |i|
      yield({ foo: i })
    end
  end
end

module ETL
  module_function

  def setup(config = {})
    Kiba.parse do
      # ... input

      transform ExplodingTransform

      # ... output
    end
  end
end
glaucocustodio commented 4 years ago

This is a known behaviour, just read at https://github.com/thbar/kiba/wiki/Implementing-ETL-transforms:

For technical reasons, this will only work in class transforms, not in block transforms

thbar commented 4 years ago

Hi @glaucocustodio!

Indeed it is a technical limitation. I believe it cannot be solved trivially with Ruby at the time.

That said you can use the following nice trick:

transform do |r|
  Enumerator.new do |y|
    2.times do |i|
      y << i
    end
  end
end

and then chain with (https://github.com/thbar/kiba-common#kibacommontransformsenumerableexploder):

transform Kiba::Common::Transforms::EnumerableExploder

This can be handy if you need to keep the yielding logic in your parse block for some reason!

I will close, since there is no known fix except the nice trick above, but please let me know if this is good enough for you!