Skip to content

Instantly share code, notes, and snippets.

@subakva
Created August 29, 2010 15:22
Show Gist options
  • Save subakva/556374 to your computer and use it in GitHub Desktop.
Save subakva/556374 to your computer and use it in GitHub Desktop.
Class to allow the creation of Rails route helpers for external applications without interfering with the application routes
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment