3

我无法在模块中动态定义类方法。请参阅下面的代码。我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: undefined local variable or method 'fruits' for Bar::ClassMethods:Module

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

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

要求:

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

阅读“Ruby 中的 Include 与 Extend”(尤其是标题为“A Common Idiom”的部分)http://www.railstips.org/blog/archives/2009/05/15/include-vs-extend-in-ruby/

非常感谢您的帮助!

4

1 回答 1

2

问题是,该fruits方法被定义为实例方法,但您在没有实例的情况下调用它ClassMethods。只需像这样定义它:

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

你的代码有效。

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

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
于 2013-07-11T18:10:46.300 回答