# Good approach to raise an exception

I have class House and module Lockable. Locking and unlocking House should reflect the real world, so you can't lock twice.

Do you think this is a good approach to using a module and raising an exception?

module Lockable

def lock!
raise StandardError, "Already locked" if @locked == true
@locked = true
end

def unlock!
raise StandardError, "Already unlocked" if @locked == false
@locked = false
end
end

class House
include Lockable
end


Usage:

house = House.new
house.lock!
house.unlock!
house.unlock! # raise an exception


I would define domain specific error classes like so:

module Lockable
Error           = Class.new StandardError

def lock!
@locked = true
end

def unlock!
@locked = false
end

def locked?
# unless already defined, this assumes an
# initial unlocked state (!!nil == false)
!!@locked
end
end


By having a common ancestor (LockedError), users can simply catch that one if they don't care about the inner state of the lockable object:

begin
house.lock!
house.lock!
rescue Lockable::Error
# meh...
rescue StandardError
# \$! needs handling
end


On the other hand, if I try to lock an already locked lock, the key just won't move (and the lock doesn't blow up in my face). So, a more realistic reflection of the world would be this implementation:

module Lockable
def lock!
@locked = true
end

def unlock!
@locked = false
end
end

• Just curious, is there a difference beteween Error = Class.new StandardError and class Error < StandardError; end? – Grych Aug 2 '14 at 10:15
• It is one char shorter. Other than that, they're equivalent. I personally don't like Ruby one-liners when they contain an ";". Declaring an error class should be a one-liner, hence the Class.new assignment. – DMKE Aug 2 '14 at 10:17