Operation
Imagine you have a class like this:
class User
def delete(id)
@users.delete id
end
end
What does it return? True? The User? an ID? What if an error occured? How does anyone calling User.delete 42
know what happened?
This is where Operation
comes in. You would just always return an Operation. That Object holds information about what happened, like so:
class User
def delete(id)
return Operation.new(code: :id_missing) unless id
return Operation.new(code: :invalid_id, id: id) unless id.match /[a-f]{8}/
user = @users[id]
if @users.delete id
Operation.new success:true, code: :user_deleted, user: user
else
Operation.new code: :deletion_failed
end
rescue ConnectionError
Operation.new code: :deletion_failed_badly
end
end
This will give you this joyful, consistent, conventional, implementation-unaware programming feeling:
operation = User.delete 42
if operation.success?
puts "It worked! You deleted the user #{operation..user.first_name}"
else
puts "Oh, could not delete User with ID #{operation.object} because #{operation.code}"
end
For your convenience you can use Operations#failure
and Operations.success
:
class User
def delete(id)
return Operations.failure(:id_missing) unless id
return Operations.failure(:invalid_id, id: id) unless id.match /[a-f]{8}/
user = @users[id]
if @users.delete id
Operations.success :user_deleted, object: user
else
Operations.failure :deletion_failed
end
rescue ConnectionError
Operation.failure :deletion_failed_badly
end
end
#object
is just a shortcut to #meta.object
:
operation = User.delete 42
operation.success? # => true
operation.object # => <#User id=42>
operation. # => <#Hashie::Mash object: <#User id=42>>
operation. # => { object: <#User id=42> }
operation.failure? # => false
Requirements
- Ruby >= 1.9
Copyright
MIT 2014 halo. See MIT-LICENSE.