Rails 获取路由列表作为带参数的路径
Rails get list of routes as paths with parameters
我想要一份我的 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中有什么方法可以做到这一点吗?
您可以尝试使用此命令:
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"
]
您可以通过使用 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
:
的 class
# 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=>"/"}, #...]
这里的优点是您可以利用现有代码收集任何已安装引擎的路由并拒绝内部路由。
我想要一份我的 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中有什么方法可以做到这一点吗?
您可以尝试使用此命令:
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"
]
您可以通过使用 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=>"/"}, #...]
这里的优点是您可以利用现有代码收集任何已安装引擎的路由并拒绝内部路由。