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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:01:55  来源:igfitidea点击:

Rails: I can't call a function in a module in /lib - what am I doing wrong?

ruby-on-railsruby

提问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_oneFoo::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_functionhttps: //apidock.com/ruby/Module/module_function