2013-06-03 34 views
3

我已经中定义的具有功能的模块:红宝石:试图object.send带有参数的模块功能

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 

我所期待的是,发送()将调用“foreign_function”方法,将字符串转换为一个符号,然后将两个参数添加到呼叫。我只想要的是没有错误,并放置到我的控制台,以便我知道它的工作......然后我将开始定义“断言”。现在,虽然我得到:

NoMethodError: undefined method `Settings::find_by_name' for #<TestFileUtilities:0x007fdf59840310> 

这是我第一次与Ruby的动态调用方法,我能得到它,当我不使用范围解析运算符的工作能力玩耍和在TestFileUtilities内部是include Settings,但我宁愿使用范围,以便用户定义的函数不会与我的类中的任何内容发生冲突(不仅与MiniTest冲突,而且与实际的FileUtilities类冲突)。任何想法/帮助将大大apprecaited!对于那些在这里寻找信息的人来说,this是让我开始的东西。

回答

1

我这个特定实例我遇到了麻烦试图包含了另一个模块中,没有任何类中的功能。我是require ing我试图发送到的模块,但是当我做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 Somethingself功能。根据我的理解,这与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 

这可能会帮助它清除掉多一点,为什么我的解决方案工作。当我发现更多的时候,我会补充到这一点。多谢你们!

1

从您的问题中不清楚类Blueprints如何与设置相关。我会假定蓝图是设置的一个子类,或者你打算使用设置。

我期待的是send()将调用“foreign_function”方法,将字符串转换为符号,然后将这两个参数添加到调用中。

你需要调用send()方法,您要发送(该对象(或类))来:

foreign_function = 'find_by_name' 
Blueprints.send(foreign_function, 'name.txt', 'Users/MCP/Desktop/Projects/TestDir') 
2

有几个问题你的榜样。

  1. 你有没有做过什么可以显着提高find_by_nameBlueprints一个类的方法,所以即使跳过send部分,你应该得到NoMethodError如果你试图调用Blueprints::find_by_name('name.txt', 'Users/MCP/Desktop/Projects/TestDir') 为了解决这个问题,你不得不说,这Blueprints.extend(Settings)会将Settings模块混入Blueprints类中,其实例方法将成为Blueprints的类方法。

  2. 方法名称是一个符号,Object#send需要一个符号作为它的第一个参数,如果它是一个字符串,它将它转换为一个符号。你传递的是字符串'Blueprints::find_by_name',这是一个非常奇怪的方法名称,而不是你定义的名称。我想你打算在类或模块Blueprints上调用方法find_by_name。要做到这一点,你可以说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 
+0

所以我意识到我在制定我的问题时弄错了复制/粘贴工作。我想要做的是调用一个模块中定义的函数。这不是在一个班级。我似乎没有尝试过任何东西,或者你建议的任何工作。所做的工作是将用户定义的函数放在该模块内部的一个类中,实例化该类的一个实例,然后在其上调用send()到一个我不知道存在的方法,但是如果用户完成了他的工作,应该是这样的......)规范可行......而且我会测试更多。只是想说谢谢,并确保我没有错过任何东西。 – MCP

+1

你似乎很困惑。 'obj.send(:foo,args)'与'obj.foo(args)'完全相同。 'send(str)'相当于'send(str.to_sym)'如果你调用模块方法,那么'obj'应该是模块。如果你正在调用实例方法,那么obj就是一个类的实例。如果你有一个你想混入另一个模块的模块,你可以使用'include'将它作为实例方法混合,'extend'作为类方法。你说我的建议不起作用 - 如果你想得到更好的帮助,请准确地展示你的尝试。 – dbenhur

+0

我是,但我到了那里。感谢您的回应。我发布了下面的工作总结。有一件事我仍然困惑,并会在今天读到,这就是模块如何在Ruby中作为对象工作。我知道用户定义的函数将存活的模块,并且在我的类文件(我试图从中发送)中要求它。我宁愿不必用'self'来定义用户定义的函数(见下文),但这是行得通的。思考? – MCP