我有一个模块,其中定义了一个函数:
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 Settings
在 TestFileUtilities
中时,我能够让它工作,但我宁愿使用范围,所以用户定义的函数与我的类中的任何内容都不冲突(不仅与 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/