Rails инициализатор, который запускается * после * загрузки маршрутов? - PullRequest
16 голосов
/ 03 января 2012

Я хочу установить атрибут класса при запуске моего приложения Rails.Требуется проверка некоторых маршрутов, поэтому маршруты должны быть загружены до запуска моего пользовательского кода.У меня проблемы с поиском надежного места для подключения.

Это работает ОТЛИЧНО в "тестовой" среде:

config.after_initialize do
  Rails.logger.info "#{Rails.application.routes.routes.map(&:path)}"
end

Но это не работает всреда "разработки" (маршруты пусты)

На данный момент у меня, похоже, все работает в режиме разработки, запуская один и тот же код в config.to_prepare, который, как я понимаю, происходит перед каждым запросом.К сожалению, использование только to_prepare не похоже на работу в тестовом режиме, следовательно, дублирование.

Мне любопытно, почему маршруты загружаются перед after_initialize в тестовом режиме, но не в режиме разработки.И действительно, что является лучшим крючком для этого?Есть ли один хук, который будет работать для всех сред?

* РЕДАКТИРОВАТЬ *

мю предложение о перезагрузке маршрутов было великолепным.Это дало мне постоянный доступ к маршрутам в after_initialize во всех средах.Однако для моего случая использования, я думаю, мне все еще нужно запускать код из to_prepare, так как я устанавливаю атрибут класса для модели, и модели перезагружаются перед каждым запросом.

Итак, вот что яв конечном итоге делает.

[:after_initialize, :to_prepare].each do |hook|
  config.send(hook) do
    User.invalid_usernames += Rails.application.routes.routes.map(&:path).join("\n").scan(/\s\/(\w+)/).flatten.compact.uniq
  end 
end 

Это кажется мне немного грязным.Я думаю, что предпочел бы сделать что-то вроде:

config.after_initialize do
  User.exclude_routes_from_usernames!
end

config.to_prepare do
  User.exclude_routes_from_usernames!
end

Но я не уверен, является ли User подходящим местом для изучения Rails.application.routes.Я думаю, я мог бы сделать то же самое с кодом в lib /, но я не уверен, что это тоже правильно.

Другой вариант - просто применить предложение mu к to_prepare.Это работает, но, кажется, есть заметная задержка перезагрузки маршрутов при каждом запросе в моей среде разработки, поэтому я не уверен, что это хороший вызов, хотя, по крайней мере, это СУХОЙ.

config.to_prepare do
  Rails.application.reload_routes!
  User.invalid_usernames += Rails.application.routes.routes.map(&:path).join("\n").scan(/\s\/(\w+)/).flatten.compact.uniq
end

Ответы [ 2 ]

23 голосов
/ 03 января 2012

Вы можете принудительно загрузить маршруты перед просмотром Rails.application.routes с помощью этого:

Rails.application.reload_routes!

Так что попробуйте это в вашем config/application.rb:

config.after_initialize do
  Rails.application.reload_routes!
  Rails.logger.info "#{Rails.application.routes.routes.map(&:path)}"
end

У меня естьсделал аналогичные вещи, которые требовались для проверки маршрутов (для конфликтов с /:slug маршрутами), и я закончил тем, что поставил reload_routes! и проверку в config.after_initialize, как вы делаете.

2 голосов
/ 06 марта 2016

Если вы пытаетесь запустить код в инициализаторе после загрузки маршрутов, вы можете попробовать использовать параметр after::

initializer "name_of_initializer", after: :add_routing_paths do |app|
  # do custom logic here
end

Вы можете найти события инициализации здесь: http://guides.rubyonrails.org/configuring.html#initialization-events

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...