Rails: фильтр, определенный в файле lib, необходимый в environment.rb, исчезает из filter_chain в производственной среде. Зачем? - PullRequest
0 голосов
/ 06 марта 2009

В моем приложении rails у меня есть файл в lib, который, помимо прочего, устанавливает фильтр, который работает на всех контроллерах.

При работе в среде разработки все работает нормально. Однако при производстве фильтр пропадает. Забавно, что, осмотрев filter_chain, я заметил, что остались другие фильтры, например. определенные в плагинах, или позже в определенном классе контроллера.

Я проверил это как с краями рельсов, так и с v2.3.0.

Обновление тестирования:

Я сейчас тестировал со старыми рельсами и обнаружил, что проблема присутствует в v2.1.0, но не в v2.0.5, я разделил их пополам и обнаружил, что рельсы 986aec5 были виноватый.


Я выделил поведение для следующего крошечного теста:

# 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'

Вот вывод, который я получаю при работе в среде development :

$ script/server &
$ curl localhost:3000/foo
> hi from foobar filter

А вот вывод для production environment:

$ 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, тестовое приложение работает правильно.

Я все еще удивляюсь, почему перезагрузка классов вызывает такую ​​вещь.

Ответы [ 2 ]

3 голосов
/ 07 марта 2009

Фредерик Чунг в списке Рельсов имел ответ :

Потому что cache_classes делает немного больше, чем это. Путь перед фильтрами, если Foo

В режиме разработки запускается приложение, требуется ваш файл, фильтр добавлен в ActionController :: Base. Позже приходит первый запрос, контроллер загружен, и он наследует этот фильтр.

Когда cache_classes равен true, все ваши классы приложений загружен раньше времени. Это происходит до того, как ваш файл требуется, поэтому все ваши контроллеры уже существуют, когда этот файл запущен и поэтому он не имеет никакого эффекта Вы можете решить эту проблему, потребовав этот файл от инициализатор (обеспечивает запуск до загрузки классов приложения), но на самом деле, почему бы вам не поместить это в application.rb?

Fred


Мое настоящее дело было гораздо более сложным, и я нашел способ решить эту проблему:

config.after_initialize do
  require 'foobar'
end

Блок after_initialize запускается после инициализации инфраструктуры, но до загрузки файлов приложения, следовательно, он повлияет на ActionPack::Base после загрузки, но до того, как будут установлены контроллеры приложений.

Полагаю, это наиболее безопасный способ справиться со всей предварительной загрузкой, которая происходит в производстве.

0 голосов
/ 07 марта 2009

Удалите скрипт ruby ​​в

RAILS_ROOT \ Config \ Инициализаторы

содержит

require "foobar.rb"

Это вызывает для меня before_filter.

...