NoMethodError: undefined method `meow?' for # - ruby mixin failing?

NoMethodError: undefined method `meow?' for # - ruby mixin failing?

我正在玩 ruby 混入的一些非常基础的东西,但出于某种原因无法从我的模块访问行为。

运行 这个在 Ruby Fiddle:

module Cats
  MEOW = "meow meow meow"

  def Cats.meow?
    return Cats::MEOW
  end
end

class Example
  include Cats

  def sample
    return "it's a sample"
  end
end

e = Example.new
puts e.sample
puts e.meow?

这会不断返回 NoMethodError: undefined method 'meow?' for #

tutorialspoint 开始,我对 mixins 应该如何工作的理解让我觉得我应该能够有效地调用 e.meow?,并得到与调用 Cats.meow? 相同的结果].

这是 RubyFiddle 中的代码。

难以置信的基础,但有什么想法让我失望了吗?

事实证明,我在定义 Cats.meow? 时过于具体了。如果你想使用一个模块作为混合你会想要更普遍地定义你的方法,而不是相对于它们特定的模块命名空间。

所以

def Cats.meow?
  ...
end

应该是

def meow?
  ...
end 

这让您可以调用 e.meow?,因为方法定义不再仅限于 Cats 命名空间。

哎呀。

作为在 Ruby 中使用 includeextend 的一般规则:

如果您想将模块用作命名空间

module Outer
  module Inner
    def self.my_method
      "namespaced method!"
    end
  end
end

你这样用Outer::Inner::my_methodOuter::Inner.my_method

如果您想将该模块用作混入:

# In some cases it makes sense to use names ending in -able, since it expreses
# what kind of messages you can send to an instance or class that mixes
# this module in.
# Like Devise's Recoverable module: https://github.com/plataformatec/devise/blob/f39c6fd92774cb66f96f546d8d5e8281542b4e78/lib/devise/models/recoverable.rb#L24

module Fooable
  def foo
    "#{self} has been foo'ed!"
  end
end

然后你可以include它(Something的实例获得#foo):

class Something
  include Fooable # Now Something.new can receive the #foo message.
end

Something.new.foo
=> "#<Something:0x0055c2dc104650> has been foo'ed!"

或者您可以扩展它(某些东西本身将 #foo 作为 class 消息获取):

class Something
  extend Fooable # Now Something can receive the #foo message.
end

Something.foo
=> "Something has been foo'ed!"