Refactor VagrantError to be more flexible so not as many subclasses will be needed

This commit is contained in:
Mitchell Hashimoto 2010-09-01 08:27:29 -07:00
parent cf91f578fb
commit f85821c268
3 changed files with 39 additions and 14 deletions

View File

@ -9,7 +9,6 @@ module Vagrant
# error code, and the error key is used as a default message from
# I18n.
class VagrantError < StandardError
DEFAULT_NAMESPACE = "vagrant.errors"
@@used_codes = []
def self.status_code(code = nil)
@ -23,19 +22,34 @@ module Vagrant
def self.error_key(key=nil, namespace=nil)
define_method(:error_key) { key }
define_method(:error_namespace) { namespace } if namespace
error_namespace(namespace) if namespace
end
def self.error_namespace(namespace)
define_method(:error_namespace) { namespace }
end
def initialize(message=nil, *args)
message = translate_error(error_key, message) if respond_to?(:error_key)
message = { :_key => message } if message && !message.is_a?(Hash)
message = { :_key => error_key, :_namespace => error_namespace }.merge(message || {})
message = translate_error(message)
super
end
# The default error namespace which is used for the error key.
# This can be overridden here or by calling the "error_namespace"
# class method.
def error_namespace; "vagrant.errors"; end
# The key for the error message. This should be set using the
# {error_key} method but can be overridden here if needed.
def error_key; ""; end
protected
def translate_error(key, opts=nil)
namespace = respond_to?(:error_namespace) ? error_namespace : DEFAULT_NAMESPACE
I18n.t("#{namespace}.#{key}", opts)
def translate_error(opts)
I18n.t("#{opts[:_namespace]}.#{opts[:_key]}", opts)
end
end

View File

@ -1,5 +1,8 @@
en:
vagrant:
errors:
test_key: This is a test key
test_key_with_interpolation: This is a test key that says %{key}
test:
errors:
test_key: This is a test key
test_key_with_interpolation: This is a test key that says %{key}
alternate:
test_key: This is an alternate

View File

@ -2,7 +2,8 @@ require "test_helper"
class ErrorsTest < Test::Unit::TestCase
setup do
@super = Vagrant::Errors::VagrantError
@klass = Vagrant::Errors::VagrantError
@super = Class.new(@klass) { error_namespace("vagrant.test.errors") }
end
should "set the given status code" do
@ -12,23 +13,30 @@ class ErrorsTest < Test::Unit::TestCase
should "raise an error if attempting to set the same status code twice" do
klass = Class.new(@super) { status_code(4445) }
assert_raises(RuntimeError) {
Class.new(@super) { status_code(4445) }
}
end
should "use the given message if no set error key" do
should "translate the given message if non-hash is given" do
klass = Class.new(@super)
assert_equal "foo", klass.new("foo").message
assert_equal I18n.t("vagrant.test.errors.test_key"), klass.new("test_key").message
end
should "use the alternate namespace if given" do
klass = Class.new(@super)
instance = klass.new(:_key => :test_key, :_namespace => "vagrant.test.alternate")
assert_equal I18n.t("vagrant.test.alternate.test_key"), instance.message
end
should "use the translation from I18n if specified" do
klass = Class.new(@super) { error_key(:test_key) }
assert_equal I18n.t("vagrant.errors.test_key"), klass.new.message
assert_equal I18n.t("vagrant.test.errors.test_key"), klass.new.message
end
should "use the translation with the options specified if key given" do
klass = Class.new(@super) { error_key(:test_key_with_interpolation) }
assert_equal I18n.t("vagrant.errors.test_key_with_interpolation", :key => "yo"), klass.new(:key => "yo").message
assert_equal I18n.t("vagrant.test.errors.test_key_with_interpolation", :key => "yo"), klass.new(:key => "yo").message
end
end