Rails未定义模块的方法

18
在Rails中,如何使用来自模块的特定方法。例如,
# ./app/controllers/my_controller.rb
class MyController < ApplicationController
  include MyModule 

  def action
    MyModule.a_method
  end

  private
  def a_method
    ...
  end
end

# ------------------------------------------------ #

# ./app/helpers/my_module.rb
module MyModule 
  def a_method
    ...
  end
end

MyController 包含了 MyModule。在 action 中,我想要使用 MyModule.a_method (请注意,我在 MyController 中也有一个私有的 a_method,我不想使用它)。

我尝试过的方法:

1)在模块中定义该方法为self.

def self.a_method
end

2) 在控制器中使用::符号(MyModule::a_method

我一直收到的错误是:Undefined method:a_method for MyModule:module。目前,我已经为模块方法使用了不同的名称。但我想知道如何使用Module::Module.符号对函数进行命名空间。

[更新-2014年11月24日]添加代码中的文件结构,因为Rails在很大程度上依赖于惯例。


你猜测 my_module.rb 是否保存在 lib/ 目录下了?你尝试在 initializer 或 application.rb 中 require 你的模块了吗? - jgraft
已更新代码部分,包含我的文件路径。 - gprasant
2个回答

26

我不太确定你使用该模块的目的是什么,但下面是一个快速解决方案来让它工作。

  1. 将my_module.rb从helpers目录移动到lib/my_module.rb中。 helpers目录是用于在视图中使用的方法的目录。传统做法是使用命名空间后跟其相应控制器或application_helper.rb为您的视图全局方法提供帮助程序。不确定这是否符合你使用该模块的目的,但还是想提出来。
  2. 在config/initializers/custom_modules.rb中创建一个初始化程序(可以随意命名),并添加require 'my_module'
  3. 将a_method更新回self.a_method
  4. 现在可以在应用程序中调用MyModule.a_method

不要忘记重新启动服务器以使更改生效。

此外,许多人参考Yehuda Katz的这篇文章作为存储应用程序代码的指南。认为这可能是一个有用的参考。


最终将模块放在lib目录中,并在初始化程序中进行了引用。 - gprasant

7
如果你将MyModule包含到MyController中,第一个的“实例方法”将被混合到第二个中。
所以,如果你只想调用MyModule.a_method,不需要包含你的模块。
然后,你需要在使用之前要求(或更好地自动加载)你的模块。为此,请将它放在controllers/concerns/my_module.rb中,Rails(至少4)应该自动加载它,否则在初始化程序中要求它的文件。
# my_module.rb
module MyModule 
  def self.a_method
    ...
  end
end

应该可以正常工作,但是有问题

# my_module.rb
module MyModule 
  extend self
  def a_method
    ...
  end
end

对我来说更加简洁易懂。您可以查看Rails Active Support Concern 以了解这个主题的“Rails方式”。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接