【问题标题】:how to properly extend ActionController in rails plugin如何在 Rails 插件中正确扩展 ActionController
【发布时间】:2009-09-07 00:39:02
【问题描述】:

我正在编写一个 Rails 插件(我们称之为 Foo)。 我希望它在控制器中提供 'bar' class 功能,这样我就可以做到:

class ApplicationController
  bar ...
end

bar 是通过插件加载文件 vendor/plugins/foo/init.rb 定义的。类似的东西

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

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

所以发生的情况是 ApplicationController 在插件“foo”之前加载并失败,因为没有定义“bar”YET

那么...我该如何正确地让它发挥作用?

我注意到许多其他扩展 ActionController 的插件(例如,inherited_resources、resource_controller 等)都在做同样的事情,所以似乎是由谁先加载来决定它是失败还是工作。

我知道我可以将代码放在某个模块中,然后在调用“foo”之前手动将该模块添加到 ApplicationController 代码中。我宁愿不,我喜欢只是 'foo' 的清洁度。

我也不想手动“要求”。插件应该是自己自动加载的:)

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    你有一个经典的插件加载顺序问题。早在 2007 年,Ryan Daigle 就有一个nice article。我将在这里总结一下推荐:

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

    【讨论】:

      【解决方案2】:

      据我了解,

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

      另外,对于扩展类,这对我来说似乎是一个更好的选择:

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

      【讨论】:

      • 并非如此。 ResourceController 引用了引用 foo 的 ApplicationController。但“bar”尚未加载,因为插件“foo”在 ResourceController 之后加载
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多