【问题标题】:Collecting first segments of all routes in rails 3收集rails 3中所有路线的第一段
【发布时间】:2012-06-03 19:28:27
【问题描述】:

我正在尝试实现第一段是配置文件别名或 id 的路由:

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

而且我需要验证别名尚未被其他(更高)路线的第一段采用。我现在拥有的是:

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... 返回空数组。但只有在模型内部验证,如果我把它放在某个地方只是为了测试它会按预期返回所有路线的第一段数组。我做错了什么还是有更好的解决方案?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 validation routes ruby-on-rails-3.2


    【解决方案1】:

    我猜你有时间问题。当您的模型在生产模式下加载时,您在Rails.application.routes 中的路由表可能尚未构建;但是,在开发模式下,您的模型可能会在每次请求时重新加载,因此当您的模型被加载并且您的 validates 调用时,Rails.application.routes 将被填充:

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

    被执行。

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

    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,到那时,路由将被加载。如果您愿意,当然可以缓存路由前缀列表。

    您还需要在应用程序的初始化阶段添加一些健全性检查。当您在开发过程中添加 /pancakes 路由时,您的生产环境中的某人可能会添加,例如,'pancakes' 作为他们的别名:您的验证将错过这个新的冲突。像这样简单的事情:

    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 中就足够了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-22
      • 2014-03-17
      相关资源
      最近更新 更多