Ruby-on-rails Rails:我无法在 /lib 中的模块中调用函数 - 我做错了什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/619840/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails: I can't call a function in a module in /lib - what am I doing wrong?
提问by Mike Woodhouse
I know I'm doing something stupid or failing to do something intelligent - I'm frequently guilty of both.
我知道我在做一些愚蠢的事情或没有做一些聪明的事情——我经常对这两种情况感到内疚。
Here's an example of what's causing me pain:
这是一个让我痛苦的例子:
I have a module saved in /lib as test_functions.rb that looks like this
我在 /lib 中有一个保存为 test_functions.rb 的模块,看起来像这样
module TestFunctions
def abc
puts 123
end
end
Going into ruby script/runner, I can see that the module is loading automatically (good ol' convention over configuration and all that...)
进入 ruby 脚本/运行程序,我可以看到模块正在自动加载(良好的 ol' 约定优于配置等等......)
>> TestFunctions.instance_methods
=> ["abc"]
so the method is known, let's try calling it
所以方法是已知的,让我们尝试调用它
>> TestFunctions.abc
NoMethodError: undefined method `abc' for TestFunctions:Module from (irb):3
Nope. How about this?
不。这个怎么样?
>> TestFunctions::abc
NoMethodError: undefined method `abc' for TestFunctions:Module from (irb):4
Test Nope again.
再次测试不行。
defined?(TestFunctions::abc) #=> nil, but
TestFunctions.method_defined? :abc #=> true
Like I said at the top, I know I'm being dumb, can anyone de-dumb me?
就像我在上面说的那样,我知道我很笨,有人可以帮我解笨吗?
采纳答案by Mike Woodhouse
I'm going to try to summarise the various answers myself, since each had something valuable to say, but none really got to what I now realise is probably the best response:
我将尝试自己总结各种答案,因为每个答案都有一些有价值的东西要说,但没有一个真正得到我现在意识到的可能是最好的答案:
I was asking the wrong question because I was doing it wrong.
我问错了问题,因为我做错了。
For reasons I can no longer explain, I wanted a set of completely stand-alone functions in a library, which represented methods I was trying to DRY out of my classes. That can be achieved, using things like
出于我无法解释的原因,我想要一个库中的一组完全独立的函数,这些函数代表我试图从我的类中删除的方法。这可以实现,使用类似的东西
module Foo
def self.method_one
end
def Foo.method_two
end
class << self
def method_three
end
end
def method_four
end
module_function :method_four
end
I could also includemy module, either within a class, in which case the methods become part of the class or outside, in which case they are defined on whatever class I'm running inside (Object? Kernel? Irb, if I'm interactive? Probably not a great idea, then)
我也include可以在类中使用我的模块,在这种情况下,方法成为类的一部分或外部,在这种情况下,它们定义在我在内部运行的任何类上(对象?内核?Irb,如果我是交互式的? 可能不是一个好主意,然后)
The thing is, there was no good reason not to have a class in the first place - I'd somehow got on to a train of thought that took me down an seldom-used and frankly slightly weird branch line. Probably a flashback to the days before OO became mainstream (I'm old enough that up to today I've spent a lot more years writing procedural code).
问题是,一开始就没有充分的理由不上课——我不知何故有了一个想法,把我带到了一条很少使用的、坦率地说有点奇怪的分支线上。可能是对面向对象成为主流之前的回忆(我已经足够大了,直到今天我已经花了很多年时间编写程序代码)。
So the functions have moved into a class, where they seem pretty happy, and the class methods thus exposed are being cheerfully used wherever necessary.
所以这些函数已经移到了一个类中,在那里它们看起来很高兴,并且在任何需要的地方都可以愉快地使用由此公开的类方法。
回答by Gareth
If you want Module-level functions, define them in any of these ways:
如果您需要Module-level 函数,请以以下任何一种方式定义它们:
module Foo
def self.method_one
end
def Foo.method_two
end
class << self
def method_three
end
end
end
All of these ways will make the methods available as Foo.method_oneor Foo::method_oneetc
所有这些方法都将使方法可用Foo.method_one或Foo::method_one等等
As other people have mentioned, instance methods in Modules are the methods which are available in places where you've included the Module
正如其他人所提到的,在实例方法Modules为你到哪儿去这地方有哪些方法included是Module
回答by Marcin Urbanski
You can also use module_function like so:
您还可以像这样使用 module_function:
module TestFunctions
def abc
puts 123
end
module_function :abc
end
TestFunctions.abc # => 123
Now you can include TestFunctions in class and call "abc" from within TestFunctions module.
现在您可以在类中包含 TestFunctions 并从 TestFunctions 模块中调用“abc”。
回答by Miles Porter
I messed with this for a while and learned several things. Hopefully this will help someone else out. I am running Rails 3.2.8.
我弄乱了一段时间并学到了一些东西。希望这会帮助其他人。我正在运行 Rails 3.2.8。
My module (utilities.rb) looks like this and is in the /lib directory of my rails app:
我的模块 (utilities.rb) 看起来像这样并且位于我的 rails 应用程序的 /lib 目录中:
module Utilities
def compute_hello(input_string)
return "Hello #{input_string}"
end
end
My test (my_test.rb) looks like this and is in the /test/unit directory of my rails app:
我的测试 (my_test.rb) 看起来像这样并且在我的 rails 应用程序的 /test/unit 目录中:
require "test_helper"
require "utilities"
class MyTest < ActiveSupport::TestCase
include Utilities
def test_compute_hello
x = compute_hello(input_string="Miles")
print x
assert x=="Hello Miles", "Incorrect Response"
end
end
Here are a few things to note: My test extends ActiveSupport::TestCase. This is important because ActiveSupport adds /lib to the $LOAD_PATH. (seehttp://stackoverflow.com/questions/1073076/rails-lib-modules-and)
这里有几点需要注意: 我的测试扩展了 ActiveSupport::TestCase。这很重要,因为 ActiveSupport 将 /lib 添加到 $LOAD_PATH。(见http://stackoverflow.com/questions/1073076/rails-lib-modules-and)
Secondly, I needed to both "require" my module file, and also "include" the module. Lastly, it is important to note that the stuff that gets included from the module essentially gets placed in the test class. So... be careful that the module that you include doesn't start with "test_". Otherwise, Rails will attempt to run your module method as a test.
其次,我需要“要求”我的模块文件,并“包含”模块。最后,重要的是要注意从模块中包含的内容实际上是放在测试类中的。所以...请注意您包含的模块不以“test_”开头。否则,Rails 将尝试运行您的模块方法作为测试。
回答by Douglas
You need to prefix your function with the module name because modules are not classes:
您需要使用模块名称作为函数的前缀,因为模块不是类:
Your /lib/test_functions.rb:
你的/lib/test_functions.rb:
module TestFunctions
def TestFunctions.abc
puts 123
end
end
Your code using the module method:
您使用模块方法的代码:
require 'test_functions'
TestFunctions.abc
回答by james
You need to include the module
您需要包含模块
include Testfunctions
include Testfunctions
Then 'abc' will return something.
然后 'abc' 会返回一些东西。
回答by Sarah Mei
You can't call a method in a Module directly. You need to include it in a class. Try this:
您不能直接调用模块中的方法。您需要将其包含在一个类中。尝试这个:
>> class MyTest
>> include TestFunctions
>> end
=> MyTest
>> MyTest.new.abc
123
=> nil
回答by Rafael Gomes Francisco
Today you can do it using module_functionnotation.
今天你可以使用module_function符号来做到这一点。
module TestFunctions
def abc
puts 123
end
end
Now TestFunctions.abcprints "123"
现在TestFunctions.abc打印“123”
A little more about module_function: https://apidock.com/ruby/Module/module_function
更多关于module_function:https: //apidock.com/ruby/Module/module_function

