我最近从resources_controller
的gem版本切换到plugin
,因为gem
版本依赖于git
。
在vendor/plugins/plugin/lib/plugin.rb
文件中,Railtie
如下:
module Ardes
module ResourcesController
class Railtie < Rails::Railtie
initializer 'ardes.resources_controller' do
ActiveSupport.on_load(:action_controller) do
extend Ardes::ResourcesController
include Ardes::ResourcesController::RequestPathIntrospection
end
ActiveSupport.on_load(:active_record) do
include Ardes::ActiveRecord::Saved
end
end
end
end
end
我在我的一个初始化器中添加了一个require 'resources_controller'
,它可以正确加载这个文件。问题是,虽然计算了Railtie
(类块中的puts
将被击中),但它似乎从未真正调用初始化块本身。这当然很重要,因为这是它扩展ActionController
以包含resources_controller_for
方法的地方。
这个问题似乎在这里和这里都出现过。尽管在这两种情况下,他们都找到了解决问题的其他方法,但没有给出为什么没有调用该块的直接答案。
从我可以告诉在Rails文档你可以命名你的初始化块任何你喜欢,它应该运行。我不认为这很重要,但我第一次注意到在生产rails s -e production
运行时的问题,虽然我相信同样的问题存在于开发模式。
发生了什么事?
作为参考,完整的插件在这里:https://github.com/ianwhite/resources_controller
这里的问题是,一旦启动了初始化过程,就不能添加新的初始化器了。
这里,您需要在初始化过程中注册初始化器的代码。当你在Gemfile中使用gems时,初始化器是在下面的代码中注册的:
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end
这段代码在初始化器开始之前执行。相反,您需要初始化程序文件中的resources_controller
代码,该文件在初始化过程中运行。因此,注册新的初始化式为时已晚。
使情况更加复杂的是,vendor/plugins
中的加载路径也是在初始化过程中设置的,因此您将无法在application.rb
中要求resources_controller
。
解决这个问题的最简单的方法是使用bundler中的:path
特性。安装完插件后,将这一行添加到Gemfile中:
gem 'resources_controller', :path => "vendor/plugins/resources_controller"
然后你可以从你的初始化器中删除require行,这样捆绑器就会识别出这个插件是一个本地检出的gem,并按照你使用git的方式来做。