我有一个模块,其中定义了一个函数:
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”方法,将字符串转换为符号,然后将两个参数添加到调用中。我想要的只是没有错误,并且放入我的控制台以便我知道它正在工作......然后我将开始定义“断言”。现在虽然我得到了:
NoMethodError: undefined method `Settings::find_by_name' for #<TestFileUtilities:0x007fdf59840310>
这是我第一次使用Ruby的动态调用方法的能力,当我没有使用范围解析运算符并且include Settings
位于TestFileUtilities
时,我能够使用它。但是我宁愿使用范围,以便用户定义的函数不会与我的类中的任何内容冲突(不仅与MiniTest冲突,而且与实际的FileUtilities类冲突)。任何想法/帮助都会非常高兴!对于那些在这里寻找信息的人来说,this是让我开始的原因。
答案 0 :(得分:2)
您的示例有几个问题。
您没有做任何明显的事情find_by_name
Blueprints
的类方法,所以即使跳过send
部分,如果你有NoMethodError
试图致电Blueprints::find_by_name('name.txt', 'Users/MCP/Desktop/Projects/TestDir')
要解决这个问题,你必须说Blueprints.extend(Settings)
将Settings模块与Blueprints类混合,其实例方法成为Blueprints的类方法。
方法名称是符号,Object#send
期望符号作为其第一个arg,如果它是一个字符串,则将其转换为符号。你传递的是字符串'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
答案 1 :(得分:1)
从您的问题不清楚蓝图类与设置的关系。我假设蓝图是“设置”的子类,或者您打算使用“设置”。
我期待的是send()将调用“foreign_function”方法,将字符串转换为符号,然后将两个参数添加到调用中。
您需要对要发送的对象(或类)调用send():( / p>
foreign_function = 'find_by_name'
Blueprints.send(foreign_function, 'name.txt', 'Users/MCP/Desktop/Projects/TestDir')
答案 2 :(得分:1)
我这个特定的例子我在尝试包含另一个模块中的函数时遇到了麻烦,而不是在任何类中。我require
正在尝试发送给我的模块,但是当我做ModuleName::send(:function_name)
时,我收到一条错误,指出“该名称不存在任何方法”(或接近该错误的内容)。修复此问题的原因是将我尝试“发送”的模块中的函数定义为“self.function_name”。
module Something
def self.my_function
puts "Silliness"
end
end
然后在发送文件/模块/类中:
require '../lib/something.rb'
class MyClass
def this_crazy_thing
funct = 'my_function'
Something::send(funct)
end
end
所以现在上述工作......只需将module Something
中的函数定义为self
即可。根据我的理解,这与如何在Ruby中实例化对象有关。让我在这里的是,不使用动态send
功能......如果我知道我想调用的模块中的函数名称,我可以用它来调用它:
ModuleName::function_name(params)
所以我期望类似的东西与send
一起使用。我的猜测是,因为我正在尝试发送到一个对象,所以该函数需要绑定到我发送给的对象,即模块,以便它可以被称为该对象的一个实例。显然,我仍然围绕着一切都是Ruby中的对象这一事实。希望这至少可以让某人走上正确的道路。如果有人可以解释为什么这有效:
module ModuleSomething
def a_function
puts "hi"
end
end
require '../lib/modulesomething'
class MyClass
def this_thing
ModuleSomething::a_function
end
end
但不是:
require 'ModuleSomething'
class MyClass
def this_string
funct = 'a_function'
ModuleSomething::send(funct)
end
end
这可能有助于澄清我的解决方案为何有效。当我发现更多时,我将添加到此。谢谢你们!