【问题标题】:Rails get list of routes as paths with parametersRails 获取路线列表作为带参数的路径
【发布时间】:2020-08-28 12:07:04
【问题描述】:

我想要一个我的 Rails 应用支持的 URL 列表,但我不想提前提供任何参数。

例如,我想将user_registration_path 的路径列为/%{locale}/users/sign_up。

我可以得到一个这样的命名路由列表(在 Rails 控制台中测试):

Rails.application.routes.named_routes.helper_names

示例输出:

["rails_info_properties_path", "rails_info_routes_path", "rails_info_path", "rails_mailers_path", "rails_service_blob_path", "rails_blob_path", "rails_blob_representation_path", "rails_representation_path", "rails_disk_service_path"...]

有什么方法可以在 Rails 中实现这一点吗?

【问题讨论】:

  • 明智的做法是dig into the source,看看Rails 是如何使用rails routes 命令实现的。在从命名路由助手跳转到应用程序的实际路由时,您还犯了一个相当大的逻辑谬误,因为并非所有路由都需要命名。
  • 您还应该知道,作为单个资源 (/users/1) 或资源组的实际地址的 URL 与描述端点的路由 (@ 987654328@).
  • 是的,我知道我会错过未命名的路线。我想我是懒惰不去寻找rails路线的来源!我应该这样做,你是绝对正确的。不过看了源码。这对我来说仍然是个谜,因为我在 Ruby 和 Rails 方面还不够熟练,无法高效地阅读这篇文章。
  • 重点是我想要一个路由名称的映射 -> 路由规范,所以我可以使用路由名称作为在前端组件中设置路由的一种方式。

标签: ruby-on-rails routes ruby-on-rails-5


【解决方案1】:

您可以尝试使用此命令:

Rails.application.routes.routes
  .map { |r| { path: r.path.spec.to_s } }

它会给你这个输出:

{:path=>"/admin/users/:id/edit(.:format)"},
{:path=>"/admin/users/:id(.:format)"},
{:path=>"/admin/users/:id(.:format)"},
{:path=>"/admin/users/:id(.:format)"},

或者作为一个数组(你可以改进它,这只是一个简单的例子):

Rails.application.routes.routes
  .flat_map { |r| r.path.spec.to_s }
  .uniq
  .map { |path| path.gsub('(.:format)', '') }
[
 "/admin/users",
 "/admin/users/new",
 "/admin/users/:id/edit",
 "/admin/users/:id"
]

【讨论】:

    【解决方案2】:

    您可以非常简单地通过使用rails routes 命令查看rails dumps the routes 来做到这一点。

    # frozen_string_literal: true
    
    require "rails/command"
    
    module Rails
      module Command
        class RoutesCommand < Base # :nodoc:
          class_option :controller, aliases: "-c", desc: "Filter by a specific controller, e.g. PostsController or Admin::PostsController."
          class_option :grep, aliases: "-g", desc: "Grep routes by a specific pattern."
          class_option :expanded, type: :boolean, aliases: "-E", desc: "Print routes expanded vertically with parts explained."
    
          def perform(*)
            require_application_and_environment!
            require "action_dispatch/routing/inspector"
    
            say inspector.format(formatter, routes_filter)
          end
    
          private
            def inspector
              ActionDispatch::Routing::RoutesInspector.new(Rails.application.routes.routes)
            end
    
            def formatter
              if options.key?("expanded")
                ActionDispatch::Routing::ConsoleFormatter::Expanded.new
              else
                ActionDispatch::Routing::ConsoleFormatter::Sheet.new
              end
            end
    
            def routes_filter
              options.symbolize_keys.slice(:controller, :grep)
            end
        end
      end
    end
    

    这里的关键是:

    inspector.format(formatter, routes_filter)
    

    格式化程序实际上只是一个响应section、header 和result 的类:

    # formats routes as a simple array of hashes
    class HashFormatter
    
      def initialize
        @buffer = []
      end
    
      # called for the main routes and also for each 
      # mounted engine
      def section(routes)
        routes.each do |r|
          @buffer << r.slice(:name, :verb, :path)
        end
      end
    
      # this method does not need to do anything since the "headers" are
      # part of the hashes
      def header(routes)
      end
    
      def result
        @buffer
      end
    end
    

    然后我们可以调用我们的格式化程序:

    inspector = ActionDispatch::Routing::RoutesInspector.new(Rails.application.routes)
    inspector.format(HashFormatter.new)
    

    并得到一个哈希数组:

    [{:name=>"", :verb=>"GET", :path=>"/pizzas/:foo(.:format)"}, {:name=>"", :verb=>"GET", :path=>"/pizzas/:foo/:bar(.:format)"}, {:name=>"", :verb=>"GET", :path=>"/pizzas/:foo/:bar/:baz(.:format)"}, {:name=>"foo", :verb=>"DELETE", :path=>"/foo(.:format)"}, {:name=>"root", :verb=>"GET", :path=>"/"}, #...]
    

    这里的优点是您可以利用现有代码收集任何已安装引擎的路由并拒绝内部路由。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多