Rails 初始化程序在加载路由*之后*运行?

问题描述 投票:0回答:3

我想在 Rails 应用程序启动时设置一个类属性。它需要检查一些路由,因此需要在我的自定义代码运行之前加载这些路由。我很难找到一个可靠的地方来挂钩。

这在“测试”环境中完美运行:

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

但是它不能在“开发”环境中工作(路线是空的)

目前,我似乎通过在

config.to_prepare
中运行相同的代码来在开发模式下工作,我知道这在每个请求之前发生。不幸的是,单独使用
to_prepare
似乎无法在测试模式下工作,因此会出现重复。

我很好奇为什么在测试模式下会在 after_initialize 之前加载路由,但在开发模式下不会加载。事实上,最好的钩子是什么?是否有一个适用于所有环境的钩子?

*编辑*

mu关于重新加载路线的建议很棒。它使我能够在所有环境中一致地访问 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 的建议。这可行,但在我的开发环境中的每个请求上重新加载路由似乎有明显的延迟,所以我不确定这是否是一个好的调用,尽管它至少是 DRY。

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
ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.1 routes initializer
3个回答
28
投票

您可以在查看

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
中,就像你正在做的那样。


4
投票

如果您尝试在加载路由后在初始化程序中运行代码,您可以尝试使用

after:
选项:

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

您可以在这里找到初始化事件:http://guides.rubyonrails.org/configuring.html#initialization-events


2
投票

Rails 确实有一个名为

config.after_routes_loaded
的配置回调,我希望在应用程序初始化和路由重新加载时都会调用它。您可以在这里找到它的文档:

https://guides.rubyonrails.org/configuring.html#config-after-routes-loaded

在 Rails 7.1.2 上,在应用程序初始化期间不会调用它;仅当路由发生变化时,才会调用它。这已在 Rails 7.1.3 中修复。相关问题是:

https://github.com/rails/rails/issues/50720

在 Rails 7.1.2 上,我通过添加类似于已接受答案中的

config.after_initialize
来规避此问题:

    config.after_initialize do
      Rails.application.reload_routes!
      ActiveSupport.run_load_hooks(:after_routes_loaded, self)
    end

之后,我可以定义我的

config.after_routes_loaded
块,并且在所有情况下都会调用它,并且在调用它时,所有路由都已加载。

观察:两个配置都在文件中定义

config/application.rb

© www.soinside.com 2019 - 2024. All rights reserved.