|
class ShareableRouteSet |
|
include ActionController::UrlWriter |
|
|
|
def initialize |
|
@route_set = ActionController::Routing::RouteSet.new |
|
@map = ActionController::Routing::RouteSet::Mapper.new(@route_set) |
|
|
|
self.draw(@map) |
|
self.install_public_helpers |
|
end |
|
|
|
# Sub-classes should override this to create their route mappings. |
|
# Ex. |
|
# map.resources :cats |
|
# map.resources :dogs |
|
def draw(map) |
|
raise RuntimeError.new('Create a sub-class of ShareableRouteSet and define the draw(map) method.') |
|
end |
|
|
|
# Loads the routes into the Rails environment. Defining your routes once in |
|
# a ShareableRouteSet, then loading them into your environment allows you to |
|
# easily package the ShareableRouteSet into a gem to be used elsewhere. |
|
def load_into_environment |
|
load_into_route_set(ActionController::Routing::Routes) |
|
end |
|
|
|
# Loads the routes into the supplied route set. |
|
def load_into_route_set(route_set) |
|
route_set.draw { |map| self.draw(map) } |
|
end |
|
|
|
# Returns the URL for the given options. This delegates to Rails' UrlWriter. |
|
def url_for_with_our_routes(options) |
|
# UrlRewriter is hard-coded to use ActionController::Routing::Routes, |
|
# so we're temporarily replacing the instance with our route set. |
|
# This is a bit of a crappy hack, but it's arguably better than copying |
|
# the code in UrlRewriter. |
|
|
|
original_routes = ActionController::Routing::Routes |
|
silence_warnings { ActionController::Routing.const_set("Routes", @route_set) } |
|
|
|
return url_for_without_our_routes(options) |
|
ensure |
|
silence_warnings { ActionController::Routing.const_set("Routes", original_routes) } |
|
end |
|
alias_method_chain :url_for, :our_routes |
|
|
|
protected |
|
|
|
def install_public_helpers |
|
# Install all the generated helpers |
|
@route_set.install_helpers(self.class) |
|
|
|
# Rails makes the helpers protected, but we want them public |
|
# in this context. |
|
|
|
# Get the list of protected methods |
|
protected_methods = self.protected_methods.collect(&:to_sym) |
|
|
|
# Remove :install_public_helpers since it should stay protected |
|
protected_methods.reject! { |sym| sym == :install_public_helpers } |
|
|
|
# Make it so. |
|
self.class.send(:public, *protected_methods) |
|
end |
|
|
|
class << self |
|
# Override default_url_options to be specific to this set of routes. |
|
def default_url_options(options = nil) |
|
@default_url_options = options unless options.nil? |
|
@default_url_options |
|
end |
|
end |
|
end |
|
|
|
# class CatRoutes < ShareableRouteSet |
|
# default_url_options(:host => 'cats.example.com') |
|
# |
|
# def draw(map) |
|
# map.resources :cats |
|
# end |
|
# end |
|
# |
|
# class DogRoutes < ShareableRouteSet |
|
# default_url_options(:host => 'dogs.example.com') |
|
# |
|
# def draw(map) |
|
# map.resources :dogs |
|
# end |
|
# end; nil |
|
# |
|
# CatRoutes.new.cats_url |
|
# DogRoutes.new.dogs_url |