【发布时间】:2013-12-19 06:22:43
【问题描述】:
在我的 Rails 项目中,我经常在我的类和模型中使用这种行为:
class Whatever
class WhateverError < StandardError; end
def initialize(params={})
raise WhateverError.new("Bad params: #{params}") if condition
# actual class code to follow
end
end
问题是,这既重复又冗长。如果我可以在需要引发特定于类的错误时执行此操作,我会很高兴:
class ErrorRaiser
include ClassErrors
def initialize(params={})
error("Bad params: #{params}") if condition
error if other_condition # has default message
# actual class code to follow
end
def self.class_method
error if third_condition # class method, behaves identically
end
end
我在创建这样一个模块时遇到了很大的麻烦。我悲伤的早期尝试看起来像下面这样,但我对模块范围内可用的内容、如何动态创建类(在方法内?)或我是否有直接的access to the "calling" class 感到很困惑。
我的基本要求是error 既是类方法又是实例方法,它对调用它的类是“命名空间”,并且它具有默认消息。有什么想法/帮助吗?这甚至可能吗?
module ClassErrorable
# This and the "extend" bit (theoretically) allow error to be a class method as well
module ClassMethods
def self.error(string=nil)
ClassErrorable.new(string).error
end
end
def self.included(base)
set_error_class(base)
base.extend ClassMethods
end
def self.set_error_class(base)
# I'm shaky on the scoping. Do I refer to this with @ in a class method
# but @@ in an instance method? Should I define it here with @ then?
@@error_class = "##{base.class}Error".constantize
end
def self.actual_error
# This obviously doesn't work, and in fact,
# it raises a syntax error. How can I make my
# constant a class inheriting from StandardError?
@@actual_error = @@error_class < StandardError; end
end
def initialize(string)
@string = string || "There's been an error!"
end
def error(string=nil)
raise @@actual_error.new(string)
end
end
【问题讨论】:
标签: ruby-on-rails ruby ruby-on-rails-3 metaprogramming