0

我正在尝试了解路由/URL 编写机制是如何工作的。我在 Rails 2.3 中,但大多数模块在 Rails 3 中是相同的。

不管怎样,rails 会为你所有格式为 resource_path 和 resource_url 的路由生成助手。

当您不带参数调用这些助手时root_path(),操作与使用额外参数调用它们时不同root_path(:random_param=>"myquery")。当您将选项传递给 _path 帮助程序时,Rails 会触发 UrlRewriter#rewrite 方法,并执行更全面的过程。

我试图找出 UrlRewriter 的触发发生在何处以及如何发生?Rails 是否实际上将“默认”无参数 url 作为字符串存储在某处?

4

1 回答 1

0

对 _path 辅助方法进行逆向工程非常困难,因为其中大部分是动态生成的。该方法并不简单,这就是 :posts 资源说完后的样子。

def posts_path(*args)  
  users_url(*args)
   args.compact! 

    return "#{ActionController::Base.relative_url_root if ActionController::Base.relative_url_root}/posts" if 
             (!defined?(default_url_options) || default_url_options.blank?) && 
             (!defined?(controller.default_url_options) || controller.default_url_options.blank?) && 
             defined?(request) && request && args.size == 0

    return "#{ActionController::Base.relative_url_root if ActionController::Base.relative_url_root}/posts#{'?' + args.last.to_query unless args.last.empty?}" if 
          (!defined?(default_url_options) || default_url_options.blank?) && 
          (!defined?(controller.default_url_options) || controller.default_url_options.blank?) && 
          defined?(request) && request && args.size == 2 && !args.last.has_key?(:anchor) && 
          !args.last.has_key?(:params) && !args.last.has_key?(:only_path) && 
          !args.last.has_key?(:host) && !args.last.has_key?(:protocol) && !args.last.has_key?(:port) && 
          !args.last.has_key?(:trailing_slash) && !args.last.has_key?(:skip_relative_url_root) && !args.last.has_key?(:subdomain)

     opts = if args.empty? || Hash === args.first   
               args.first || {}                                                          
            else                                                                        
               options = args.extract_options!                                           
               args = args.zip([:format]).inject({}) do |h, (v, k)|  
                 h[k] = v                                                                
                 h                                                                       
               end                                                                       
               options.merge(args)                                                       
            end 

            url_for(hash_for_posts_path(opts))                         
          end 

路由模块积极尝试优化路由解析。'return' 语句是由 rails 或用户库/gems 动态构建的各种条件,用于解析路线,而无需最后通过该url_for()方法。顺便说一句,这是 ActionController#Base.url_for。

正如第一个“return”语句所示,如果 args.size == 0,此方法将返回“/posts”,这意味着当该方法被调用时不带参数,即posts_path()。如果没有返回语句成功,则使用 url_for 启动 UrlRewrite。

如果您有很多依赖于 url_for 被调用的逻辑(这是我的情况),那么您需要重新考虑。因为“返回”条件是动态生成的,所以无法可靠地预测该方法是否会返回默认路径或尝试执行重写。

如果有人有更多信息要添加到此答案中,请编辑。

于 2013-09-19T15:14:38.787 回答