collectiveidea/interactor — pull request #20 by emilford (2013-09-14 13:12:01+00:00)
Title: Add halt! to abort without rollback

I'm still working on a few more (and better?) use cases, but wanted to go ahead and open this to spark further discussion from where we left off in [i] campfire. I still argue that there is a need, semantically and functionally, for a means to stop a chain of interactors in this manner.

The example is maybe a bit contrived* but at least offers another example to base discussions around. The point is to introduce a means to stop execution of subsequent interactors in a way that is not deemed a failure and, more importantly, does not force any unwanted rollback behavior without the need for successive "check" flags. In my opinion, halt! is a valid success case.

*Also thought of a bank paying a check, but kept getting bogged down with the details in the example this early in the morning. The gist was paybychecking -> halt! unless hasoverdraft -> paybecredit.

``ruby
class ProcessCustomerOrder
include Interactor::Organizer

organize [

# No-op
#
# rollback
# - NotifyAdmin.new(message)
NotifyException

# Charge customer for purchase.
#
# fail!(message: oh no!)
# rollback
# - give money back
ChargeCustomer

# Send now or queue for later?
#
# fail!(message: oh no!)
CheckAvailableInventory
unless inventory.available?
CheckAvailabilityLater.enqueue(order)
halt!(message: "Success: Ships 2-4 weeks!")
end

# Send goods to customer
#
# fail!(message: oh no!)
# rollback
# - ensure order canceled
DeliverGoods
if goods.deliver!
halt!(message: "Success: Arrives 2-4 days!")
# or (both are success cases)
# context[:message] = "Success: Arrives 2-4 days!"
else
fail!(message: oh no!)
end

]
end

def create
process_order = ProcessOrder.new(order: order)

if process_order.success?
redirect_to whatever_path, notice: process_order.message
else
render :uh_oh
end
end
```