在 Rails 中动态重新加载路由是一个坏主意吗? [英] Is it a bad idea to reload routes dynamically in Rails?

查看:38
本文介绍了在 Rails 中动态重新加载路由是一个坏主意吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个应用程序,我允许管理员为页面、类别等添加别名,并且我想根据别名使用不同的控制器/操作(无需重定向,并且我'我发现 render 实际上并没有调用该方法.我只是渲染了模板).我已经尝试了一条捕获所有路线,但我并不热衷于导致和捕获每次抛出的 DoubleRender 异常.

I have an application I'm writing where I'm allowing the administrators to add aliases for pages, categories, etc, and I would like to use a different controller/action depending on the alias (without redirecting, and I've found that render doesn't actually call the method. I just renders the template). I have tried a catch all route, but I'm not crazy about causing and catching a DoubleRender exception that gets thrown everytime.

对此我提出的解决方案是在服务器启动时动态生成路由,并在创建/更新/销毁别名时使用别名模型的回调来重新加载路由.这是我的 routes.rb 中的代码:

The solution for this I've come up with is dynamically generated routes when the server is started, and using callbacks from the Alias model to reload routes when an alias is created/updated/destroyed. Here is the code from my routes.rb:

Alias.find(:all).each do |alias_to_add|
    map.connect alias_to_add.name, 
            :controller => alias_to_add.page_type.controller, 
            :action => alias_to_add.page_type.action,
            :navigation_node_id => alias_to_add.navigation_node.id
end

我在 Alias 模型中使用回调如下:

I am using callbacks in my Alias model as follows:

after_save :rebuild_routes
after_destroy :rebuild_routes

def rebuild_routes
    ActionController::Routing::Routes.reload!
end

这是否违反了 Rails 最佳实践?有没有更好的解决方案?

Is this against Rails best practices? Is there a better solution?

推荐答案

快速解决方案

在 routes.rb 的底部有一个包罗万象的路由.在将您路由到的操作中实现您想要的任何别名查找逻辑.

Quick Solution

Have a catch-all route at the bottom of routes.rb. Implement any alias lookup logic you want in the action that route routes you to.

在我的实现中,我有一个表,将定义的 URL 映射到控制器、操作和参数哈希.我只是将它们从数据库中取出,然后调用适当的操作,然后尝试呈现该操作的默认模板.如果动作已经渲染了一些东西,就会抛出一个 DoubleRenderError,我会发现并忽略它.

In my implementation, I have a table which maps defined URLs to a controller, action, and parameter hash. I just pluck them out of the database, then call the appropriate action and then try to render the default template for the action. If the action already rendered something, that throws a DoubleRenderError, which I catch and ignore.

您可以将这种技术扩展为您想要的复杂程度,尽管随着它变得更复杂,通过调整您的路由或 Rails 默认路由逻辑而不是通过本质上自己重新实现所有路由逻辑来实现它更有意义.

You can extend this technique to be as complicated as you want, although as it gets more complicated it makes more sense to implement it by tweaking either your routes or the Rails default routing logic rather than by essentially reimplementing all the routing logic yourself.

如果您没有找到别名,您可以根据需要抛出 404 或 500 错误.

If you don't find an alias, you can throw the 404 or 500 error as you deem appropriate.

缓存:事先不知道您的 URL 会使页面缓存成为绝对负担.请记住,它基于提供的 URI 进行缓存,而不是基于 url_for (:action_you_actually_executed).这意味着如果你别名

Caching: Not knowing your URLs a priori can make page caching an absolute bear. Remember, it caches based on the URI supplied, NOT on the url_for (:action_you_actually_executed). This means that if you alias

/foo_action/bar_method

/some-wonderful-alias

你会在你的缓存目录中得到 some-wonderful-alias.html.当您尝试扫描 foo 的栏时,除非您明确指定,否则您不会扫描该文件.

you'll get some-wonderful-alias.html living in your cache directory. And when you try to sweep foo's bar, you won't sweep that file unless you specify it explicitly.

容错:检查以确保某人不会意外地在现有路由上设置别名.您可以通过将所有别名强制到一个已知不可路由的目录"来轻松完成此操作(在这种情况下,别名在文本上是唯一的足以确保它们永远不会发生冲突),但这并不是最理想的我能想到的一些应用程序的解决方案.

Fault Tolerance: Check to make sure someone doesn't accidentally alias over an existing route. You can do this trivially by forcing all aliases into a "directory" which is known to not otherwise be routable (in which case, the alias being textually unique is enough to make sure they never collide), but that isn't a maximally desirable solution for a few of the applications I can think of of this.

这篇关于在 Rails 中动态重新加载路由是一个坏主意吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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