我需要创建一个可以在任何情况下使用的方法(MVC,测试等)。而不是将其填充到environments.rb
id中,而不是创建模块并将其包含为gem。为了让Rails识别这个模块中的方法,我需要在gem中扩展哪个类?
更新
我正在寻找一种解决方案,允许我在没有模块前缀的情况下调用我的方法。
答案 0 :(得分:8)
你需要"延伸" Kernel
模块,将您的方法包含在include
中。
通常是"全球" Ruby中的方法意味着在Kernel
或Object
中创建方法。然后,该方法可用于所有(大多数)类,因为它们继承自Object
(包括Kernel
)。您的方法可以在大多数地方没有前缀的情况下调用,因为任何给定上下文中的隐式self
都是从Object
继承的对象,因此包含您定义的方法。
定义此类方法的一种方法是将其定义放在任何类或模块之外的文件中:
def my_method
# do fancy stuff
end
当然,您必须确保文件在某处加载(即需要)。
如果您希望在一个模块中组织您的方法(这是一个好主意),您需要将该模块包含在Kernel
中,如下所示:
module MySpecialMethods
def my_method
# do fancy stuff
end
end
module Kernel
private
include MySpecialMethods # This is where the method gets added to Kernel
end
在Rails中,我会将MySpecialMethods
模块放在lib/
中,将Kernel
部分添加到初始化文件config/initializers/extend_kernel.rb
中。你还需要帮助Rails"找到"将lib/
添加到application.rb
config.autoload_paths += %W(#{config.root}/lib)
中的模块
在极少数情况下以这种方式扩展Kernel
是一个好主意,这一点毫无价值。可能(可能?)对于您的情况,将您的方法放在模块中并使用类似MyModule.my_method
的模块名称显式调用它们更好。
module MyModule
def self.my_method
# do fancy stuff here
end
end
您可以在许多位置放置此代码。在Rails中,我建议将其放在上面的lib/
文件夹中,然后确保Rails可以通过将config.autoload_paths += %W(#{config.root}/lib)
添加到application.rb来找到它。
创建gem超出了这个问题的范围,但假设您创建了一个gem,只要您在Gemfile中指定gem,通常只需在Rails应用程序中使用该gem中的模块。这是因为Rails应用程序默认调用Bundler.require
。只要gem遵循正确的命名约定,主要的gem文件就会自动生成,而主gem文件需要任何其他必要的文件。
如果您想从gem扩展Kernel
,只需将Kernel
扩展代码(从上面)放入需要(直接或间接)需要gem的文件中。
Rails初始化程序仅在您启动Rails服务器时运行一次,因此对它们的更改不会像开发中的许多其他Rails一样自动加载。
如果您正在调整Rails' autoload_paths
,您可能还想调整eager_load_paths
(请参阅this blog post)
Ruby中有个对象做 继承自Object
(例如BasicObject ),技术上这些"全球" 无处不在的方法。这不太可能给你带来麻烦。
在Rails应用中使用Bundler.require
可能会引起争议(有关详情,请参阅this blog post)