我有一个模块,其中定义了一个函数:

module Settings
def find_by_name(name, start)
  puts "find_by_name: Found me!"
end

在 miniTest 中,我试图以一种模拟它在运行时动态定义/调用的方式来测试“发送”到这个函数。这是我在 MiniTest 中尝试做的事情。
require 'settings'

class TestFileUtilities < MiniTest::Unit::TestCase

  def test_dynamic_call_to_Settings
    foreign_function = 'Settings::find_by_name'
    send(foreign_function, 'name.txt', 'Users/MCP/Desktop/Projects/TestDir')
  end

我期望的是 send() 将调用“foreign_function”方法,将字符串转换为符号,然后将两个参数添加到调用中。我想要的只是没有错误,并且向我的控制台输入一个 puts 以便我知道它正在工作……然后我将开始定义“断言”。现在虽然我得到:
NoMethodError: undefined method `Settings::find_by_name' for #<TestFileUtilities:0x007fdf59840310>

这是我第一次使用 Ruby 动态调用方法的能力,当我没有使用范围解析运算符并且 include SettingsTestFileUtilities 中时,我能够让它工作,但我宁愿使用范围,所以用户定义的函数与我的类中的任何内容都不冲突(不仅与 MiniTest 冲突,而且与实际的 FileUtilities 类冲突)。任何想法/帮助将不胜感激!对于偶然在这里寻找信息的任何人,this 是让我开始的原因。

最佳答案

你的例子有几个问题。

  • 你没有做任何明显的事情来使 find_by_name 成为 Blueprints 的类方法,所以即使跳过 send 部分,如果你试图调用 NoMethodError 也应该得到 Blueprints::find_by_name('name.txt', 'Users/MCP/Desktop/Projects/TestDir')为了解决这个问题,你必须说 Blueprints.extend(Settings) 它将设置模块混合到蓝图类,其实例方法成为蓝图的类方法。
  • 方法名是一个符号, Object#send 期望一个符号作为它的第一个参数,如果它是一个字符串,它会将其转换为一个符号。您正在传递字符串 'Blueprints::find_by_name' ,这是一个非常奇怪的方法名称,而不是您定义的名称。我认为您打算在类或模块 find_by_name 上调用方法 Blueprints 。为此,您可以说 foreign_function = 'find_by_name'; Blueprints.send(foreign_function, 'name.txt', 'Users/MCP/Desktop/Projects/TestDir') 如果您也需要动态解析类/模块名称,则需要 Module#const_get

  • 所以这就是我认为你想说的:
    module Settings
      def find_by_name(name, start)
        puts "find_by_name: Found me!"
      end
    end
    
    class Blueprints
      extend Settings
    end
    
    require 'settings'
    
    class TestFileUtilities < MiniTest::Unit::TestCase
    
      def test_dynamic_call_to_actual_Blueprints
        klass = 'Blueprints'
        func = 'find_by_name'
        Object.const_get(klass).send(func, 'name.txt', 'Users/MCP/Desktop/Projects/TestDir')
      end
    
    end
    

    关于Ruby:尝试向对象发送带有参数的模块函数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16888646/

    10-12 21:05