2008-01-09 21:51:09 -05:00
module ActionController
2006-08-24 02:15:01 -04:00
# Write URLs from arbitrary places in your codebase, such as your mailers.
2008-01-09 21:51:09 -05:00
#
2006-08-24 02:15:01 -04:00
# Example:
2008-01-09 21:51:09 -05:00
#
2006-08-24 02:15:01 -04:00
# class MyMailer
# include ActionController::UrlWriter
# default_url_options[:host] = 'www.basecamphq.com'
2008-01-09 21:51:09 -05:00
#
2006-08-24 02:15:01 -04:00
# def signup_url(token)
# url_for(:controller => 'signup', action => 'index', :token => token)
# end
# end
2008-01-09 21:51:09 -05:00
#
2006-08-24 02:15:01 -04:00
# In addition to providing +url_for+, named routes are also accessible after
# including UrlWriter.
module UrlWriter
# The default options for urls written by this writer. Typically a :host pair
# is provided.
mattr_accessor :default_url_options
self . default_url_options = { }
2008-01-09 21:51:09 -05:00
2006-08-24 02:15:01 -04:00
def self . included ( base ) #:nodoc:
2008-01-09 21:51:09 -05:00
ActionController :: Routing :: Routes . install_helpers ( base )
2006-08-24 02:15:01 -04:00
base . mattr_accessor :default_url_options
base . default_url_options || = default_url_options
end
2008-01-09 21:51:09 -05:00
# Generate a url based on the options provided, default_url_options and the
2007-08-16 21:11:11 -04:00
# routes defined in routes.rb. The following options are supported:
2008-01-09 21:51:09 -05:00
#
2007-08-16 21:08:16 -04:00
# * <tt>:only_path</tt> If true, the relative url is returned. Defaults to false.
# * <tt>:protocol</tt> The protocol to connect to. Defaults to 'http'.
2008-01-09 21:51:09 -05:00
# * <tt>:host</tt> Specifies the host the link should be targetted at. If <tt>:only_path</tt> is false, this option must be
# provided either explicitly, or via default_url_options.
2007-08-16 21:08:16 -04:00
# * <tt>:port</tt> Optionally specify the port to connect to.
# * <tt>:anchor</tt> An anchor name to be appended to the path.
2008-01-09 21:51:09 -05:00
# * <tt>:skip_relative_url_root</tt> If true, the url is not constructed using the relative_url_root set in <tt>ActionController::AbstractRequest.relative_url_root</tt>.
#
2007-08-16 21:08:16 -04:00
# Any other key(:controller, :action, etc...) given to <tt>url_for</tt> is forwarded to the Routes module.
2008-01-09 21:51:09 -05:00
#
2007-08-16 21:08:16 -04:00
# Examples:
2008-01-09 21:51:09 -05:00
#
2007-08-16 21:08:16 -04:00
# url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :port=>'8080' # => 'http://somehost.org:8080/tasks/testing'
# url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true # => '/tasks/testing#ok'
# url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33' # => 'http://somehost.org/tasks/testing?number=33'
2006-08-24 02:15:01 -04:00
def url_for ( options )
options = self . class . default_url_options . merge ( options )
2008-01-09 21:51:09 -05:00
2006-08-24 02:15:01 -04:00
url = ''
2007-03-03 17:19:54 -05:00
2008-01-09 21:51:09 -05:00
unless options . delete ( :only_path )
2006-09-06 18:21:36 -04:00
url << ( options . delete ( :protocol ) || 'http' )
2008-01-09 21:51:09 -05:00
url << '://' unless url . match ( " :// " )
2006-09-06 18:21:36 -04:00
raise " Missing host to link to! Please provide :host parameter or set default_url_options[:host] " unless options [ :host ]
2007-03-03 17:19:54 -05:00
2006-09-06 18:21:36 -04:00
url << options . delete ( :host )
url << " : #{ options . delete ( :port ) } " if options . key? ( :port )
else
2008-01-09 21:51:09 -05:00
# Delete the unused options to prevent their appearance in the query string.
[ :protocol , :host , :port , :skip_relative_url_root ] . each { | k | options . delete ( k ) }
2006-09-06 18:21:36 -04:00
end
2007-03-03 17:19:54 -05:00
2008-01-09 21:51:09 -05:00
url << ActionController :: AbstractRequest . relative_url_root . to_s unless options [ :skip_relative_url_root ]
anchor = " # #{ CGI . escape options . delete ( :anchor ) . to_param . to_s } " if options [ :anchor ]
2006-08-24 02:15:01 -04:00
url << Routing :: Routes . generate ( options , { } )
2007-05-02 00:40:33 -04:00
url << anchor if anchor
2007-03-03 17:19:54 -05:00
2008-01-09 21:51:09 -05:00
url
end
2006-08-24 02:15:01 -04:00
end
2008-01-09 21:51:09 -05:00
2005-02-07 09:15:53 -05:00
# Rewrites URLs for Base.redirect_to and Base.url_for in the controller.
2004-11-23 20:04:44 -05:00
class UrlRewriter #:nodoc:
2007-02-25 15:22:09 -05:00
RESERVED_OPTIONS = [ :anchor , :params , :only_path , :host , :protocol , :port , :trailing_slash , :skip_relative_url_root ]
2005-02-14 20:45:35 -05:00
def initialize ( request , parameters )
@request , @parameters = request , parameters
2004-11-23 20:04:44 -05:00
end
2008-01-09 21:51:09 -05:00
2006-06-29 22:36:17 -04:00
def rewrite ( options = { } )
2007-03-03 17:19:54 -05:00
rewrite_url ( options )
2004-11-23 20:04:44 -05:00
end
def to_str
2005-06-24 12:40:01 -04:00
" #{ @request . protocol } , #{ @request . host_with_port } , #{ @request . path } , #{ @parameters [ :controller ] } , #{ @parameters [ :action ] } , #{ @request . parameters . inspect } "
2004-11-23 20:04:44 -05:00
end
2005-02-14 20:45:35 -05:00
alias_method :to_s , :to_str
2004-11-23 20:04:44 -05:00
private
2007-03-27 10:04:06 -04:00
# Given a path and options, returns a rewritten URL string
2007-03-03 17:19:54 -05:00
def rewrite_url ( options )
2004-11-23 20:04:44 -05:00
rewritten_url = " "
2007-03-03 17:19:54 -05:00
2005-07-23 05:00:05 -04:00
unless options [ :only_path ]
rewritten_url << ( options [ :protocol ] || @request . protocol )
2007-02-25 15:22:09 -05:00
rewritten_url << " :// " unless rewritten_url . match ( " :// " )
2007-03-03 17:19:54 -05:00
rewritten_url << rewrite_authentication ( options )
2005-07-23 05:00:05 -04:00
rewritten_url << ( options [ :host ] || @request . host_with_port )
2007-02-25 15:22:09 -05:00
rewritten_url << " : #{ options . delete ( :port ) } " if options . key? ( :port )
2005-07-23 05:00:05 -04:00
end
2004-11-23 20:04:44 -05:00
2007-07-14 05:28:56 -04:00
path = rewrite_path ( options )
2005-04-17 10:10:24 -04:00
rewritten_url << @request . relative_url_root . to_s unless options [ :skip_relative_url_root ]
2007-07-14 05:28:56 -04:00
rewritten_url << ( options [ :trailing_slash ] ? path . sub ( / \ ?| \ z / ) { " / " + $& } : path )
2004-11-23 20:04:44 -05:00
rewritten_url << " # #{ options [ :anchor ] } " if options [ :anchor ]
2005-02-14 20:45:35 -05:00
2005-06-24 12:40:01 -04:00
rewritten_url
2004-11-23 20:04:44 -05:00
end
2007-03-27 10:04:06 -04:00
# Given a Hash of options, generates a route
2005-07-17 23:25:53 -04:00
def rewrite_path ( options )
options = options . symbolize_keys
options . update ( options [ :params ] . symbolize_keys ) if options [ :params ]
2007-03-03 17:19:54 -05:00
2005-09-06 18:06:11 -04:00
if ( overwrite = options . delete ( :overwrite_params ) )
2005-09-07 04:59:33 -04:00
options . update ( @parameters . symbolize_keys )
2007-01-28 00:29:32 -05:00
options . update ( overwrite . symbolize_keys )
2005-09-06 18:06:11 -04:00
end
2007-03-03 17:19:54 -05:00
RESERVED_OPTIONS . each { | k | options . delete ( k ) }
2005-03-26 19:01:56 -05:00
2006-06-01 11:42:08 -04:00
# Generates the query string, too
2006-06-01 12:20:26 -04:00
Routing :: Routes . generate ( options , @request . symbolized_path_parameters )
2004-11-23 20:04:44 -05:00
end
2008-01-09 21:51:09 -05:00
2007-03-03 17:19:54 -05:00
def rewrite_authentication ( options )
if options [ :user ] && options [ :password ]
2007-03-04 15:10:51 -05:00
" #{ CGI . escape ( options . delete ( :user ) ) } : #{ CGI . escape ( options . delete ( :password ) ) } @ "
2007-03-03 17:19:54 -05:00
else
" "
end
end
2004-11-23 20:04:44 -05:00
end
2007-07-14 05:28:56 -04:00
end