1

我有这个模块:

module Api
  module ObjectMapper
    def self.const_missing const_name

      anon_class = Class.new do
        def self.foo
          puts self.class.name
        end
      end

      const_set const_name, anon_class
    end
  end
end

我希望能够在运行时使用foo可以调用的方法定义一个匿名类Api::ObjectMapper::User::foo。该功能应该打印User到屏幕上。我尝试过的一切都导致了某种错误或功能打印Class到屏幕上。

如何修复我的类和方法定义,以便 self.class.name 正确解析?

4

3 回答 3

1

我找到了解决方案。由于您是在 const_missing 方法的范围内定义匿名类,因此您可以使用 const_name ,这是您正在定义的类的名称。我不确定这是否是最好的解决方案,但它确实有效。你必须像这样重新定义你的类:

  anon_class = Class.new do
    define_singleton_method(:foo) do
      puts const_name
    end
  end
于 2013-09-17T14:10:30.043 回答
1

类的名称只是引用它的第一个常量。原始代码的唯一问题是您使用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
于 2013-09-17T14:32:55.170 回答
-1

您还可以将 foo 方法定义为类方法

def self.const_missing const_name
  anon_class = Class.new do
    def self.foo
      puts self.class.name
    end
  end
end
于 2013-09-17T14:17:16.057 回答