Good approach to raise an exception
I would define domain specific error classes like so:

module Lockable
  Error           = Class.new StandardError
  AlreadyLocked   = Class.new Error
  AlreadyUnlocked = Class.new Error

  def lock!
    raise AlreadyLocked if locked?
    @locked = true
  end

  def unlock!
    raise AlreadyUnlocked unless locked?
    @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