如何在rails插件中正确扩展ActionController

我正在写一个Rails插件(让我们称之为Foo)。 我希望它在控制器中提供’bar’ function,这样我就可以:

class ApplicationController bar ... end 

bar是使用插件加载文件vendor / plugins / foo / init.rb定义的。 就像是

 class ActionController::Base def self.bar ... end end 

问题是其他一些插件(在我的情况下是ResourceController)可能会 foo 之前加载并访问ApplicationController。

所以会发生什么是在插件’foo’之前加载ApplicationController并且因为没有’bar’定义YET而失败。

所以…我如何正确地使其工作?

我注意到许多其他扩展ActionController的插件(例如inherited_resources,resource_controller)正在做同样的事情,所以看起来是谁首先加载以决定它是否失败或工作。

我知道我可以将代码放在某个模块中,并在调用’foo’之前手动将模块添加到ApplicationController代码中。 我宁愿不,我喜欢’foo’的清洁。

我也不想做手册’要求’。 插件本身应该自动加载:)

你有什么是经典的插件加载顺序问题。 Ryan Daigle在2007年有一篇很好的文章 。我将在这里总结一下这个建议:

 # in RAILS_ROOT/config/environment.rb: ... Rails::Initializer.run do |config| # load Bar before Foo, then everything else: config.plugins = [ :bar, :foo, :all ] ... end 

据我所知,

ResourceController在插件foo之前加载并尝试使用你在foo定义的bar方法。 通常,在应用程序类之前加载gem和plugins。 (看看rails/railties/lib/initializer.rb )。 你能提供一个错误的堆栈跟踪,以便可以调试它。

此外,为了扩展课程,这似乎是一个更好的替代方案:

 module ActionController class Base class << self ... # Class methods here end ... # Instance methods here end end