Created
June 4, 2015 06:12
-
-
Save mark-ellul/b530ea8fa31bc8afe408 to your computer and use it in GitHub Desktop.
A new router to get around having a subdomain constraint in your apps routes
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module AePageObjects | |
class SubdomainApplicationRouter < AePageObjects::BasicRouter | |
# This whole file is a kludge and probably belongs in an ae_page_objects-rails extension | |
module Recognizer | |
class Base | |
def generate_path(named_route, *args) | |
if routes.respond_to?("#{named_route}_path") | |
if args.count == 1 | |
args[0].merge!({host: "test.lvh.me:3000"}) | |
end | |
routes.send("#{named_route}_path", *args) | |
end | |
end | |
def recognizes?(named_route, url) | |
url = normalize_url(url) | |
resolved_named_route = resolve_named_route(named_route) | |
[:get, :post, :put, :delete, :patch].each do |method| | |
resolved_route_from_url = resolve_url(url, method) | |
# The first resolved route matching named route is returned as | |
# Rails' routes are in priority order. | |
if resolved_named_route == resolved_route_from_url | |
return true | |
end | |
end | |
false | |
end | |
private | |
def routes | |
raise NotImplementedError, "You must implement routes" | |
end | |
def normalize_url(url) | |
raise NotImplementedError, "You must implement normalize_url" | |
end | |
def router | |
raise NotImplementedError, "You must implement router" | |
end | |
def resolve_named_route(named_route) | |
requirements = router.named_routes[named_route].requirements | |
ResolvedRoute.new(requirements[:controller], requirements[:action]) | |
end | |
def resolve_url(url, method) | |
recognized_path = router.recognize_path("http://test.lvh.me#{url}", {:method => method, "subdomain" => "test"}) | |
ResolvedRoute.new(recognized_path[:controller], recognized_path[:action]) | |
rescue ActionController::RoutingError, ActionController::MethodNotAllowed | |
end | |
ResolvedRoute = Struct.new(:controller, :action) | |
end | |
class Rails23 < Base | |
private | |
def routes | |
@routes ||= begin | |
routes_class = Class.new do | |
include ActionController::UrlWriter | |
end | |
ActionController::Routing::Routes.install_helpers(routes_class) | |
routes_class.new | |
end | |
end | |
def normalize_url(url) | |
url | |
end | |
def router | |
ActionController::Routing::Routes | |
end | |
end | |
class Rails3 < Base | |
private | |
def request_for(url, method) | |
::Rails.application.routes.request_class.new(env_for(url, method)) | |
end | |
def env_for(url, method) | |
begin | |
Rack::MockRequest.env_for(url, {:method => method, "subdomain" => "test"}) | |
rescue URI::InvalidURIError => e | |
raise ActionController::RoutingError, e.message | |
end | |
end | |
def normalize_url(url) | |
Rack::Mount::Utils.normalize_path(url) unless url =~ %r{://} | |
end | |
def router | |
::Rails.application.routes | |
end | |
def routes | |
@routes ||= begin | |
routes_class = Class.new do | |
include ::Rails.application.routes.url_helpers | |
end | |
routes_class.new | |
end | |
end | |
end | |
class Rails32 < Rails3 | |
private | |
def normalize_url(url) | |
Journey::Router::Utils.normalize_path(url) unless url =~ %r{://} | |
end | |
end | |
class Rails4 < Rails32 | |
private | |
def normalize_url(url) | |
require 'action_dispatch/journey' | |
ActionDispatch::Journey::Router::Utils.normalize_path(url) unless url =~ %r{://} | |
end | |
end | |
end | |
def path_recognizes_url?(path, url) | |
if path.is_a?(Symbol) | |
recognizer.recognizes?(path, url) | |
else | |
super | |
end | |
end | |
def generate_path(named_route, *args) | |
if named_route.is_a?(Symbol) | |
recognizer.generate_path(named_route, *args) | |
else | |
super | |
end | |
end | |
private | |
def recognizer | |
@recognizer ||= begin | |
if ::Rails.version =~ /\A2\.3/ | |
Recognizer::Rails23.new | |
elsif ::Rails.version =~ /\A3\.[01]/ | |
Recognizer::Rails3.new | |
elsif ::Rails.version =~ /\A3\.2/ | |
Recognizer::Rails32.new | |
elsif ::Rails.version =~ /\A4\.[012]/ | |
Recognizer::Rails4.new | |
else | |
warn "[WARNING]: AePageObjects is not tested against Rails #{::Rails.version} and may behave in an undefined manner." | |
Recognizer::Rails4.new | |
end | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment