如何在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