类的名称只是引用它的第一个常量。原始代码的唯一问题是您使用self.class.name
而不是self.name
:
module Api
module ObjectMapper
def self.const_missing const_name
self.const_set const_name, Class.new{
def self.foo
name.split('::').last
end
}
end
end
end
p Api::ObjectMapper::User, #=> Api::ObjectMapper::User
Api::ObjectMapper::User.name, #=> "Api::ObjectMapper::User"
Api::ObjectMapper::User.foo #=> "User"
当您定义类方法(类上的单例方法)时,self
就是类。self.class
是故常,其Class
名是"Class"
。
原始答案,返回“用户”而不是“Api::ObjectMapper::User”
一种方法(不比基于闭包的解决方案更好)是在类上使用实例变量:
module Api
module ObjectMapper
def self.const_missing const_name
anon_class = Class.new do
def self.foo
puts @real_name
end
end
anon_class.instance_variable_set(:@real_name,const_name)
const_set const_name, anon_class
end
end
end
Api::ObjectMapper::User.foo
#=> User
几个替代的,更严格的语法:
def self.const_missing const_name
const_set const_name, Class.new{
def self.foo; puts @real_name end
}.tap{ |c| c.instance_eval{ @real_name = const_name } }
end
def self.const_missing const_name
const_set const_name, Class.new{
def self.foo; puts @real_name end
}.instance_eval{ @real_name = const_name; self }
end