本文介绍了收集铁轨中所有路线的第一部分3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实施第一段为配置文件别名或ID的路由:

I'm trying to implement routes where the first segment is the profile's alias or id:

resources :profiles, :path => '' do
    ...
end

我需要验证其他(较高)路由的第一个路段尚未采用别名。我现在所拥有的是:

And I need to validate that alias is not already taken by first segments of other(higher) routes. What I have now is:

validates :alias, :exclusion => {:in => Rails.application.routes.routes.map{|r| r.path.spec.to_s.split('(').first.split('/').second}.compact.uniq },
                  ....

开发中一切正常,生产中 Rails.application.routes.routes.map ... 返回空数组。但是仅在模型内部验证中,如果我将它放在某个地方以进行测试以按预期返回所有路由的第一段数组。我在做什么错了,或者有更好的解决方案?

In development everything is ok. In production Rails.application.routes.routes.map... returns empty array. But only inside validation in model, if I put it somewhere in view just to test it returns array of first segments of all routes as expected. What am I doing wrong or maybe there is a better solution?

推荐答案

我猜你有一个计时问题,你在 Rails.application.routes 在生产模式下加载模型时可能尚未构建;但是在开发模式下,您的模型可能会在每次请求时重新加载,因此 Rails.application.routes 将在加载模型并验证 时填充:

I'd guess that you have a timing problem. Your routing table in Rails.application.routes probably hasn't been built when your model is loaded in production mode; but, in development mode, your model is probably being reloaded on each request so Rails.application.routes will be populated when your model is loaded and your validates call:

validates :alias, :exclusion => { :in => Rails.application.routes.routes.map { ... } }

被执行。

一个简单的解决方案是切换到验证方法:

An easy solution would be to switch to a validation method:

class Model < ActiveRecord::Base
    validate :alias_isnt_a_route, :if => :alias_changed?

private

    def alias_isnt_a_route
        routes = Rails.application.routes.routes.map { ... }
        if(routes.include?(alias))
            errors.add(:alias, "Alias #{alias} is already used for a route")
    end
end

通过这种方式,您无需查看 Rails.application.routes ,直到需要检查别名,到那时,路由将已加载。当然,您可以根据需要缓存路由前缀列表。

This way, you don't look at Rails.application.routes until you need to check an alias and by that time, the routes will have been loaded. You could, of course, cache the route prefix list if you wanted to.

您还需要在应用程序的初始化阶段添加一些完整性检查。生产环境中的某人可以在添加 / pancakes 路由时添加'pancakes'作为别名发展中:您的验证将错过这个新的冲突。像这样简单的事情:

You'll also want to add some sanity checking to your application's initialization phase. Someone in your production environment could add, say, 'pancakes' as their alias while you add a /pancakes route while developing: your validation will miss this new conflict. Something simple like this:

config.after_initialize do
    Rails.application.reload_routes! # Make sure the routes have been loaded.
    # Compare all the existing aliases against the route prefixes and raise an
    # exception if there is a conflict.
end

在您的 config / application.rb 就足够了。

这篇关于收集铁轨中所有路线的第一部分3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-11 12:15