在*路由加载后运行的Rails初始化程序? [英] Rails initializer that runs *after* routes are loaded?

查看:93
本文介绍了在*路由加载后运行的Rails初始化程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的Rails应用程序启动时设置一个class属性。它需要检查一些路由,因此在我的自定义代码运行之前,需要先加载路由。我在寻找可靠的挂接位置时遇到麻烦。

I want to set a class attribute when my Rails app starts up. It requires inspecting some routes, so the routes need to be loaded before my custom code runs. I am having trouble finding a reliable place to hook in.

这在测试环境中可以正常工作:

This works PERFECTLY in the "test" environment:

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

但是它在开发环境中起作用(路线是空的)

But it doesn't work in the "development" environment (the routes are empty)

目前,我似乎通过在 config.to_prepare 据我了解,发生在每个请求之前。不幸的是,单独使用 to_prepare 在测试模式下似乎不起作用,因此重复。

For now I seem to have things working in development mode by running the same code in config.to_prepare which I understand happens before every request. Unfortunately using to_prepare alone doesn't seem to work in test mode, hence the duplication.

我很好奇为什么在测试模式下而不在开发模式下在after_initialize之前加载路由。确实,对此最好的钩子是什么?

I'm curious why the routes are loaded before after_initialize in test mode, but not in development mode. And really, what is the best hook for this? Is there a single hook that will work for all environments?

* EDIT *

*EDIT*

mu对重新加载路线的建议很棒。它使我能够在所有环境中对after_initialize中的路由进行一致的访问。不过对于我的用例,我认为我仍然还需要从to_prepare运行代码,因为我要在模型上设置类属性,并且在每次请求之前都会重新加载模型。

mu's suggestion of reloading the routes was great. It gave me consistent access to the routes within after_initialize in all environments. For my use case though, I think I still need to run the code from to_prepare as well, since I'm setting a class attribute on a model and the models are reloaded before each request.

所以这就是我最终要做的事情。

So here's what I ended up doing.

[: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 

对我来说似乎有点混乱。我想我愿意这样做:

It seems a bit messy to me. I think I'd rather do something like:

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 /中的代码做同样的事情,但我不确定这是否正确。

But I'm not sure if User is the right place to be examining Rails.application.routes. I guess I could do the same thing with code in lib/ but I'm not sure if that's right either.

另一种选择是将mu的建议应用于to_prepare。可以,但是在我的开发环境中,每次请求重新加载路由时似乎都存在明显的延迟,因此我不确定这是一个不错的选择,尽管至少是DRY。

Another option is to just apply mu's suggestion on to_prepare. That works but there seems to be a noticeable delay reloading the routes on every request in my dev environment, so I'm not sure if this is a good call, although it's DRY, at least.

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


推荐答案

您可以在查看 Rails.application.routes 之前强制加载以下路由:

You can force the routes to be loaded before looking at Rails.application.routes with this:

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 中进行检查。

I've done similar things that needed to check the routes (for conflicts with /:slug routes) and I ended up putting the reload_routes! and the checking in a config.after_initialize like you're doing.

这篇关于在*路由加载后运行的Rails初始化程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆