Rails:environment.rb中所需的lib文件中定义的过滤器从生产环境中的filter_chain中消失。为什么?

StackOverflow https://stackoverflow.com/questions/620146

在我的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.rbconfig.cache_classestrue更改为false,则测试应用程序可以正常运行。

我仍然想知道为什么课程重新加载导致这样的事情。

有帮助吗?

解决方案

Rails列表上的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 ,但在应用程序控制器之前。

我想这是处理生产过程中所有预加载的一般安全方法。

其他提示

删除

中的ruby脚本
  

RAILS_ROOT \设置\初始化

包含

require "foobar.rb"

这会为我调用before_filter。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top