README.md in transflow-0.0.2 vs README.md in transflow-0.1.0

- old
+ new

@@ -28,12 +28,12 @@ - a business transaction doesn't have any state - each operation shouldn't accumulate state, instead it should receive an input and return an output without causing any side-effects - the only interface of a an operation is `#call(input)` - each operation provides a meaningful functionality and can be reused -- each operation can broadcast its result (TODO) -- external message consumers can listen to a transaction object for specific events (TODO) +- each operation can broadcast its result +- external message consumers can listen to a transaction object for specific events ## Why? The rationale for this project is quite simple - every use-case in an application can be described as a series of processing steps where some input is turned into @@ -51,58 +51,104 @@ yet but *probably* using pub/sub for that will do the work as we can register an error listener that can simply gather errors and return it as a result. ## Synopsis +Using Transflow is ridiculously simple as it doesn't make much assumptions about +your code. You provide container with operations and they simply need to respond +to `#call(input)` and return output or raise an error if something went wrong. + +### Defining a simple flow + ``` ruby DB = [] container = { - validate: -> input { raise "name nil" if input[:name].nil? }, + validate: -> input { input[:name].nil? ? raise("name nil") : input }, persist: -> input { DB << input[:name] } } -my_business_flow = Transflow(container: container) do - step(:validate) { step(:persist) } -end +my_business_flow = Transflow(container: container) { steps :validate, :persist } my_business_flow[{ name: 'Jane' }] puts DB.inspect # ["Jane"] +``` -## The same but with events +## Defining a flow with event publishers -NOTIFICATIONS = [] +In many cases an individual operation may require additional behavior to be +triggered. This can be easily achieved with a pub/sub mechanism. Transflow +provides that mechanism through the wonderful `wisper` gem which is used under +the hood. -class Notify - def persist_success(user) +``` ruby +DB = [] + +NOTIFICATIONS = [] # just for the sake of the example + +class UserPersistListener + def self.persist_success(user) NOTIFICATIONS << "#{user} persisted" end - def persist_failure(user, err) + def self.persist_failure(user, err) # do sth about that end end my_business_flow = Transflow(container: container) do step(:validate) { step(:persist, publish: true) } end -notify = Notify.new +my_business_flow.subscribe(persist: UserPersistListener) -my_business_flow.subscribe(persist: notify) - my_business_flow[{ name: 'Jane' }] puts DB.inspect # ["Jane"] puts NOTIFICATIONS.inspect # ["Jane persisted"] ``` +### Passing additional arguments + +Another common requirement is to pass aditional arguments that we don't have in +the moment of defining our flow. Fortunately Transflow allows you to pass any +arguments in the moment you call the transaction. Those arguments will be curried +which means you must use either procs as your operation or an object that responds +to `curry`. This limitation will be removed soon. + +``` ruby +DB = [] + +operations = { + preprocess_input: -> input { { name: input['name'], email: input['email'] } }, + # let's say this one needs additional argument called `email` + validate_input: -> email, input { input[:email] == email ? input : raise('ops') }, + persist_input: -> input { DB << input[:name] } +} + +transflow = Transflow(container: operations) do + step :preprocess, with: :preprocess_input do + step :validate, with: :validate_input do + step :persist, with: :persist_input + end + end +end + +input = { 'name' => 'Jane', 'email' => 'jane@doe.org' } + +# here we say "for `validate` operation curry this additional argument +transflow[input, validate: 'jane@doe.org'] + +puts DB.inspect +# ["Jane"] +``` + ## Installation Add this line to your application's Gemfile: ```ruby @@ -115,18 +161,14 @@ Or install it yourself as: $ gem install transflow -## Usage - -TODO: Write usage instructions here - ## Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). ## Contributing -Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/transflow. +Bug reports and pull requests are welcome on GitHub at https://github.com/solnic/transflow.