RSPEC说'未定义的方法'在包含另一个模块的模块上运行时

发布于 2025-02-05 12:28:50 字数 417 浏览 2 评论 0 原文

我的情况是当前:

module Base
 module A
  include Base::B
 end
end

module Base
 module B
  module_function
  def my_method
   ...
  end
 end
end

然后我的测试:

Rspec.describe Base::A do
 describe '.my_method' do
  it 'does something'
   ...
  end
 end
end

问题:

nomethoderror。未定义的方法'my_method'for Base :: a:模块

我缺少什么?提前致谢!

my situation is the current:

module Base
 module A
  include Base::B
 end
end

module Base
 module B
  module_function
  def my_method
   ...
  end
 end
end

And then my test:

Rspec.describe Base::A do
 describe '.my_method' do
  it 'does something'
   ...
  end
 end
end

Problem:

NoMethodError. undefined method `my_method' for Base::A:Module

What am I missing? Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

野鹿林 2025-02-12 12:28:50
module Base
  module B
    module_function

    def my_method
      "you've found me!"
    end
  end
end

module Base
  module A
    include Base::B
  end
end

module_function 让我们可以通过定义单例方法在模块上调用我们的方法( my_method 的完整单独副本):

>> Base::B.singleton_methods
=> [:my_method]
>> Base::B.my_method
=> "you've found me!"

它也将 my_method 转换为一个私有方法,这是您在“包括”或“扩展”时获得的方法:

>> Base::B.private_instance_methods
=> [:my_method]

# NOTE: we can call this version of `my_method` by including or 
#       extending the module in a class.
#       using `send` to call private methods outside the class.

class Included
  include Base::B
end

>> Included.private_instance_methods
=> [:my_method, ...]
>> Included.new.send(:my_method)
=> "you've found me!"

class Extended
  extend Base::B
end

# this would be a private class method
>> Extended.private_methods
=>[:my_method, ...]
>> Extended.send(:my_method)
=> "you've found me!"

# NOTE: very simple rules to keep in mind
#
#   instance method => include => instance method
#   instance method => extend  => method

如果 base :: b 包含在 base :: a 模块中:

>> Base::B.private_instance_methods
=> [:my_method]

# NOTE: we cannot call `my_method` on the module, because we do not get a 
#       singleton method (or private method)
>> Base::A.singleton_methods
=> []

# there is the expected instance method, made private by using `module_function`
>> Base::A.private_instance_methods
=> [:my_method]

# only we can't call `.new` on a module.
>> Base::A.new.send(:my_method)
`<main>': undefined method `new' ...

因为我们无法在模块中初始化一个实例,我们可以通过将 base :: A 使用 self 扩展到类方法。

module Base
  module A
    include Base::B
    extend self # extend Base::A, add instance methods to (class) methods
  end
end

>> Base::A.private_methods
=> [:my_method, ...]
>> Base::A.send(:my_method)
=> "you've found me!"

或扩展 base :: b 从开始:

module Base
  module A
    extend Base::B
  end
end

>> Base::A.send(:my_method)
=> "you've found me!"

module_function 执行等效:

module Base
  module C
    # NOTE: singleton method stays in this module
    def self.my_method
      "singleton my_method"
    end
    
    private

    # NOTE: instance method gets included/extended
    def my_method
      "private instance my_method"
    end
  end
end

Base::C.my_method                               # => "singleton my_method"
Class.new.extend(Base::C).send(:my_method)      # => "private instance my_method"
Class.new.include(Base::C).new.send(:my_method) # => "private instance my_method"
Module.new.extend(Base::C).send(:my_method)     # => "private instance my_method"
Module.new.include(Base::C).send(:my_method)    # => undefined method
Module.new{extend self}.include(Base::C).send(:my_method)
                                                # => "private instance my_method"

https://ruby-doc.org/core-core-core-3.1.2/module.html#metml#method-method-i-i-i-module_function

https> https:/// Ruby-doc.org/core-3.1.2/module.html#method-i-include

https://ruby-doc.org/core-3.1.2/Object.html#method-i-extend< /em>

module Base
  module B
    module_function

    def my_method
      "you've found me!"
    end
  end
end

module Base
  module A
    include Base::B
  end
end

module_function lets us call our method on the module by defining a singleton method (a full separate copy of my_method):

>> Base::B.singleton_methods
=> [:my_method]
>> Base::B.my_method
=> "you've found me!"

It also turns my_method into a private method, this is the method you get when "including" or "extending":

>> Base::B.private_instance_methods
=> [:my_method]

# NOTE: we can call this version of `my_method` by including or 
#       extending the module in a class.
#       using `send` to call private methods outside the class.

class Included
  include Base::B
end

>> Included.private_instance_methods
=> [:my_method, ...]
>> Included.new.send(:my_method)
=> "you've found me!"

class Extended
  extend Base::B
end

# this would be a private class method
>> Extended.private_methods
=>[:my_method, ...]
>> Extended.send(:my_method)
=> "you've found me!"

# NOTE: very simple rules to keep in mind
#
#   instance method => include => instance method
#   instance method => extend  => method

Same rules apply if Base::B is included in Base::A module:

>> Base::B.private_instance_methods
=> [:my_method]

# NOTE: we cannot call `my_method` on the module, because we do not get a 
#       singleton method (or private method)
>> Base::A.singleton_methods
=> []

# there is the expected instance method, made private by using `module_function`
>> Base::A.private_instance_methods
=> [:my_method]

# only we can't call `.new` on a module.
>> Base::A.new.send(:my_method)
`<main>': undefined method `new' ...

Since we can't initialize an instance out of the module, we can bump the instance method to a class method by extending Base::A with self.

module Base
  module A
    include Base::B
    extend self # extend Base::A, add instance methods to (class) methods
  end
end

>> Base::A.private_methods
=> [:my_method, ...]
>> Base::A.send(:my_method)
=> "you've found me!"

or extend Base::B from the start:

module Base
  module A
    extend Base::B
  end
end

>> Base::A.send(:my_method)
=> "you've found me!"

module_function does the equivalent of this:

module Base
  module C
    # NOTE: singleton method stays in this module
    def self.my_method
      "singleton my_method"
    end
    
    private

    # NOTE: instance method gets included/extended
    def my_method
      "private instance my_method"
    end
  end
end

Base::C.my_method                               # => "singleton my_method"
Class.new.extend(Base::C).send(:my_method)      # => "private instance my_method"
Class.new.include(Base::C).new.send(:my_method) # => "private instance my_method"
Module.new.extend(Base::C).send(:my_method)     # => "private instance my_method"
Module.new.include(Base::C).send(:my_method)    # => undefined method
Module.new{extend self}.include(Base::C).send(:my_method)
                                                # => "private instance my_method"

https://ruby-doc.org/core-3.1.2/Module.html#method-i-module_function

https://ruby-doc.org/core-3.1.2/Module.html#method-i-include

https://ruby-doc.org/core-3.1.2/Object.html#method-i-extend

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文