When I originally kicked things off, I added a lot of big transactions around various api-call-surrounding-database-ops. This was knowingly a cheap hack to avoid bad state changes and delaying the inevitable: careful and tedious handling of errors and control-flow.
I'm now slowly refactoring things to unpack these big transactions and I realize many of them are actually unnecessary. I'm employing yet another cheap Result
object to signify boundary-states,
Result = Struct.new(:ok?, :error, :value, keyword_init: true)
def good_op
Result.new(ok?: true, value: 1)
end
def bad_op
Result.new(ok?: false, error: "Did not work")
end
operation.ok?
operation.value
operation.error
This is a little bit silly, because it requires you to ensure that value
is only present alongside the ok?
and the others are falsey in the error
case. But it is very simple and quick to get a refactor busted out.
I have used Github::Result in the past, but recently discovered dry-rb -- many of these look very sensible and immediately useful. Hopefully the next step!