Skip to content

Instantly share code, notes, and snippets.

@scottmessinger
Created July 15, 2015 18:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scottmessinger/c62bb892087957a315f5 to your computer and use it in GitHub Desktop.
Save scottmessinger/c62bb892087957a315f5 to your computer and use it in GitHub Desktop.
Importer with Transproc
preprocessor = Preprocessor.build
processor = Processor.build
evaluator = InputFunctions[:eval_values, [{ 'jd' => 'jd001' }]]
create_authors_with_books = rom.command([
:authors, [:create, [:books, [:create]]]
])
module Flow
extend Transproc::Registry
def self.preprocess(input)
preprocessor.call(input)
end
def self.validate(input)
if input.all? { |author| Validator.new(author).valid? }
input
end
end
def self.process(input)
processor.call(input).map { |author| evaluator.call(author) } if input
end
def self.persist(input)
create_authors_with_books.call(authors: input) if input
end
end
result = Flow(:preprocess) >> Flow(:validate) >> Flow(:process) >> Flow(:persist)
result.call(raw_input)
@jmgarnier
Copy link

I have 2 questions:

  1. Is there a way to use instance methods in Flow module instead of class methods? Why class methods?
  2. Could the if input part be abstracted or moved to Transproc ?

@scottmessinger
Copy link
Author

Great questions.

  1. A couple reasons. To my knowledge, Transproc needs class (or in this case, module) methods. Second, and this is a personal thing, I prefer module methods because it forces them to be stateless and pure functions. @solnic does something fascinating with ROM where he uses instances but all the instance methods don't mutate the instance, essentially making them class methods operating on a private state. Perhaps how OO should be but certainly not how it's practiced.
  2. That's a great question. I'm not sure, but I think so. If it could, I'm unsure if it would add more clarity. When I've used this pattern, I find I really like having the if logic in the method because then I can add the method to a flow and it will only execute if the params have the right parameters. Makes the methods far more resuseable and easier to compose.

@solnic
Copy link

solnic commented Sep 22, 2015

We have :guard in transproc that goes like this:

irb(main):004:0> require 'transproc/all'
=> true
irb(main):005:0> include Transproc::Registry
irb(main):006:0> import Transproc::Conditional
=> main
irb(main):007:0> t(:guard, -> input { input > 1 }, -> input { puts 'MORE THAN 1!' })[2]
MORE THAN 1!
=> nil

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment