19

我想在我的 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
4

2 回答 2

29

您可以在查看之前强制加载路线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

于 2012-01-03T03:47:25.213 回答
3

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

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

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

于 2016-03-06T05:31:07.607 回答