在我的rails应用程序中,我在lib中有一个文件,除其他外,它设置了一个在所有控制器上运行的过滤器。
在开发环境下运行时,一切运行正常。但是,在生产过程中,过滤器会丢失。有趣的是,通过检查filter_chain
,我注意到其他过滤器仍然存在,例如。插件中定义的那些,或稍后在特定控制器类中定义的那些。
我用rails edge和v2.3.0进行了测试。
我现在已经使用较旧的rails进行了测试,发现问题出现在v2.1.0中,但在v2.0.5中没有,我将它们一分为二,发现986aec5 rails承诺有罪。
我已将行为分离到以下微小的测试用例:
# app/controllers/foo_controller.rb
class FooController < ApplicationController
def index
render :text => 'not filtered'
end
end
# lib/foobar.rb
ActionController::Base.class_eval do
before_filter :foobar
def foobar
render :text => 'hi from foobar filter'
end
end
# config/environment.rb (at end of file)
require 'foobar'
以下是在开发环境下运行时获得的输出:
$ script/server &
$ curl localhost:3000/foo
> hi from foobar filter
这是生产环境的输出:
$ script/server -e production &
$ curl localhost:3000/foo
> not filtered
如前所述,当我通过插件执行相同操作时,它适用于任何环境。我只需要将lib/foobar.rb
下的内容放在插件的init.rb
文件中。
所以在某种程度上我已经有了解决方法,但我想了解发生了什么以及导致过滤器在生产中失踪的原因。
我猜想Rails在不同环境中处理加载的方式不同,但我需要深入挖掘。
实际上,我现在已将其缩小到以下配置行:
config.cache_classes = false
如果production.rb
,config.cache_classes
从true
更改为false
,则测试应用程序正常运行。
我仍然想知道为什么课程重新加载导致这样的事情。
答案 0 :(得分:3)
Rails list the answer上的Frederick Cheung:
因为cache_classes做的不仅仅是那个。方式 在过滤器工作之前,如果Foo&lt; Bar然后只定义那些过滤器 此时的栏将由Foo继承 - 将它们添加到Bar的a 以后的日期不会做任何事情
在开发模式下,应用程序启动,您的文件是必需的,过滤器 添加到ActionController :: Base。后来第一个请求出现了, 控制器已加载,它继承了该过滤器。
当cache_classes为true时,那么所有的应用程序类都是 提前加载。这在您的文件需要之前发生,所以 当该文件运行时,所有控制器都已存在 没有效果。您可以通过要求此文件来解决此问题 初始化程序(确保它在加载应用程序类之前运行),但是 真的为什么不把它放在application.rb中?
佛瑞德
我的真实情况实际上涉及的更多,这是我找到解决问题的方式:
config.after_initialize do
require 'foobar'
end
after_initialize
块在框架初始化之后但在加载应用程序文件之前运行,因此,它会在加载之后但在应用程序控制器之前影响ActionPack::Base
。
我想这是处理生产过程中所有预加载的一般安全方法。
答案 1 :(得分:0)
删除
中的ruby脚本RAILS_ROOT \设置\初始化
包含
require "foobar.rb"
这会为我调用before_filter。