我正在玩一些ruby mixins的基础知识,并且由于某种原因无法访问我的模块中的行为。
在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?
时我过于具体。如果要将模块用作mixin,则需要更一般地定义方法,而不是针对其特定的模块命名空间。
而不是
def Cats.meow?
...
end
应该是的
def meow?
...
end
这使您可以调用e.meow?
,因为方法定义不再仅限于Cats
命名空间。
哎呦。
作为在Ruby中使用include
和extend
的一般规则:
如果要将模块用作命名空间
module Outer
module Inner
def self.my_method
"namespaced method!"
end
end
end
你使用它像Outer::Inner::my_method
或Outer::Inner.my_method
。
如果你想将模块用作mixin:
# 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!"
或者你可以扩展它(Something本身将#foo作为类消息获得):
class Something
extend Fooable # Now Something can receive the #foo message.
end
Something.foo
=> "Something has been foo'ed!"