Ruby:在模块中动态定义类方法

标签 ruby metaprogramming

我在模块中动态定义类方法时遇到问题。请参阅下面的代码。尝试引用模块中的另一个类方法时,我得到一个 NameError: undefined local variable or method。看起来这可能是一个范围或上下文问题,但到目前为止我还没有弄清楚。

module Bar

  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods

    def fruits
      ["apple", "orange", "banana"]
    end

    def example_function(string)
      string.upcase
    end

    fruits.each do |fruit|
      method_name = fruit.to_sym
      define_method(method_name) { example_function(fruit) }
    end

  end

end

class Foo
  include Bar
end

puts Foo.apple
puts Foo.orange
puts Foo.banana

我希望能够调用:

puts Foo.apple => "APPLE"
puts Foo.orange => "ORANGE"
puts Foo.banana => "BANANA"

目前,当我尝试其中任何一个时,我都会收到以下错误: NameError:Bar::ClassMethods:Module 的未定义局部变量或方法“fruits”

此外,Bar::ClassMethods 中的类方法应该对 Foo 可用,所以我应该能够调用:

puts Foo.fruits => ["apple", "orange", "banana"]

要求:

  1. 所有代码都在一个模块中。
  2. 该模块允许混合使用实例方法和类方法(见下文)。
  3. 目标方法是动态定义的。

阅读“Ruby 中的包含与扩展”(尤其是标题为“常见习语”的部分)http://www.railstips.org/blog/archives/2009/05/15/include-vs-extend-in-ruby/

非常感谢您的帮助!

最佳答案

问题是,fruits 方法被定义为实例方法,但您在 ClassMethods 上调用它时没有实例。像这样定义它:

def self.fruits
  ["apple", "orange", "banana"]
end

并且您的代码有效。

编辑: 要使 fruits 方法也作为 Foo 上的类方法可访问,您必须以在内部可访问的方式声明 fruits 数组ClassMethods 模块。一种方法是将数组声明为类变量,并在 fruits 方法和 each block 中使用它。看下面的代码:

module Bar

  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    @@fruits = ["apple", "orange", "banana"]

    def fruits
      @@fruits
    end

    def example_function(string)
      string.upcase
    end

    @@fruits.each do |fruit|
      method_name = fruit.to_sym
      define_method(method_name) { example_function(fruit) }
    end
  end
end

class Foo
  include Bar
end

puts Foo.apple
puts Foo.orange
puts Foo.banana
puts Foo.fruits

关于Ruby:在模块中动态定义类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17600190/

相关文章:

ruby - 如何从 Ruby 中的哈希中删除特定值

python - 结合 Python 和 Ruby 扩展模块

c++ - 在 C++ 中自动/模板化生成测试 vector

mysql - 如何运行数据库 :setup in Capistrano 3 and Rails 4

ruby - rcov 外轨

ruby - 如何构建带有子对象的 Mongoid 对象的 json 对象?

c++ - 与运行时相比,为什么三元运算符在编译时的工作方式不同?

c++ - QObject 通用信号处理程序

javascript - 在 Javascript/Coffeescript/jQuery 中是否有与 Ruby 的发送等效的东西?

c++ - c++中swap是如何实现的