Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Created April 27, 2015 05:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshCheek/fae6b046dd9f6bcd1dbf to your computer and use it in GitHub Desktop.
Save JoshCheek/fae6b046dd9f6bcd1dbf to your computer and use it in GitHub Desktop.
Playing with the Rails Router in isolation
class Route
def initialize(route)
@route = route
end
def to_s
string = ""
string << "#{verb} request to #{path} will dispatch to the class #{controller.camelize}, and call the method #{action}.\n"
string << "#{controller.camelize} is expected to be defined in #{controller_file}\n"
string << "There are #{helper_methods.length} helper methods you can call in the controller and the view: #{helper_methods}\n" if helper_methods.any?
string
end
def to_h
{ verb: verb, path: path, controller: controller.camelize, action: action, controller_file: controller_file, helper_methods: helper_methods }
end
def inspect
"#<Route #{name} #{verb} #{path} to #{controller}##{action}>"
end
def controller_file
"app/controllers/#{controller}.rb"
end
def controller
"#{@route.defaults[:controller]}_controller"
end
def action
@route.defaults[:action]
end
def verb
@route.verb.source[1...-1] # verb is a regexp like /^GET$/
end
def path
@route.path.ast.to_s
end
def url(host="http://example.com")
File.join(host, path)
end
def name
@route.name
end
def helper_methods
return [] unless name
[path_helper, url_helper]
end
def path_helper
name && "#{name}_path"
end
def url_helper
name && "#{name}_url"
end
end
require 'action_dispatch/routing'
route_set = ::ActionDispatch::Routing::RouteSet.new
route_set.draw do
root 'site#index'
resources :ducks, only: [:index, :show] do
member { get :pond }
end
end
routes = route_set.routes.map { |route| Route.new route }
# ===== Rake Routes output =====
require 'action_dispatch/routing/inspector'
Rails ||= Class.new { def self.method_missing(*) self end } # hack to get around router coupling
ActionDispatch::Routing::RoutesInspector.new(route_set.routes).format(ActionDispatch::Routing::ConsoleFormatter.new).lines
# => [" Prefix Verb URI Pattern Controller#Action\n",
# " root GET / site#index\n",
# "pond_duck GET /ducks/:id/pond(.:format) ducks#pond\n",
# " ducks GET /ducks(.:format) ducks#index\n",
# " duck GET /ducks/:id(.:format) ducks#show"]
# ===== Path Helpers =====
path_routes = routes.select { |r| r.path_helper }
helper_width = path_routes.flat_map { |r| r.path_helper }.map(&:length).max
path_routes.map { |r| "%-#{helper_width}s | %s" % [r.path_helper, r.path] }
# => ["root_path | /",
# "pond_duck_path | /ducks/:id/pond(.:format)",
# "ducks_path | /ducks(.:format)",
# "duck_path | /ducks/:id(.:format)"]
# ===== Url Helpers =====
url_routes = routes.select { |r| r.url_helper }
helper_width = url_routes.flat_map { |r| r.path_helper }.map(&:length).max
url_routes.map { |r| "%-#{helper_width}s | %s" % [r.url_helper, r.url] }
# => ["root_url | http://example.com/",
# "pond_duck_url | http://example.com/ducks/:id/pond(.:format)",
# "ducks_url | http://example.com/ducks(.:format)",
# "duck_url | http://example.com/ducks/:id(.:format)"]
# ===== Explanation =====
puts routes.join("\n")
# >> GET request to / will dispatch to the class SiteController, and call the method index.
# >> SiteController is expected to be defined in app/controllers/site_controller.rb
# >> There are 2 helper methods you can call in the controller and the view: ["root_path", "root_url"]
# >>
# >> GET request to /ducks/:id/pond(.:format) will dispatch to the class DucksController, and call the method pond.
# >> DucksController is expected to be defined in app/controllers/ducks_controller.rb
# >> There are 2 helper methods you can call in the controller and the view: ["pond_duck_path", "pond_duck_url"]
# >>
# >> GET request to /ducks(.:format) will dispatch to the class DucksController, and call the method index.
# >> DucksController is expected to be defined in app/controllers/ducks_controller.rb
# >> There are 2 helper methods you can call in the controller and the view: ["ducks_path", "ducks_url"]
# >>
# >> GET request to /ducks/:id(.:format) will dispatch to the class DucksController, and call the method show.
# >> DucksController is expected to be defined in app/controllers/ducks_controller.rb
# >> There are 2 helper methods you can call in the controller and the view: ["duck_path", "duck_url"]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment