Upgraded Rails and RSpec
[monkeycharger.git] / vendor / rails / actionpack / lib / action_controller / url_rewriter.rb
blobc650763fdbce26a1382f86cd01ab731311c3148e
1 module ActionController  
2   # Write URLs from arbitrary places in your codebase, such as your mailers.
3   # 
4   # Example:
5   # 
6   #   class MyMailer
7   #     include ActionController::UrlWriter
8   #     default_url_options[:host] = 'www.basecamphq.com'
9   #     
10   #     def signup_url(token)
11   #       url_for(:controller => 'signup', action => 'index', :token => token)
12   #     end
13   #  end
14   # 
15   # In addition to providing +url_for+, named routes are also accessible after
16   # including UrlWriter.
17   module UrlWriter
18     # The default options for urls written by this writer. Typically a :host pair
19     # is provided.
20     mattr_accessor :default_url_options
21     self.default_url_options = {}
22     
23     def self.included(base) #:nodoc:
24       ActionController::Routing::Routes.install_helpers base 
25       base.mattr_accessor :default_url_options
26       base.default_url_options ||= default_url_options
27     end
28     
29     # Generate a url based on the options provided, default_url_options and the 
30     # routes defined in routes.rb.  The following options are supported:
31     # 
32     # * <tt>:only_path</tt> If true, the relative url is returned. Defaults to false.
33     # * <tt>:protocol</tt> The protocol to connect to. Defaults to 'http'.
34     # * <tt>:host</tt> Specifies the host the link should be targetted at. If <tt>:only_path</tt> is false, this option must be 
35     #   provided either explicitly, or via default_url_options. 
36     # * <tt>:port</tt> Optionally specify the port to connect to.
37     # * <tt>:anchor</tt> An anchor name to be appended to the path.
38     # 
39     # Any other key(:controller, :action, etc...) given to <tt>url_for</tt> is forwarded to the Routes module.
40     # 
41     # Examples:
42     # 
43     #    url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :port=>'8080'    # => 'http://somehost.org:8080/tasks/testing'
44     #    url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :anchor => 'ok', :only_path => true    # => '/tasks/testing#ok'
45     #    url_for :controller => 'tasks', :action => 'testing', :host=>'somehost.org', :number => '33'  # => 'http://somehost.org/tasks/testing?number=33'
46     # 
47     def url_for(options)
48       options = self.class.default_url_options.merge(options)
49       
50       url = ''
52       unless options.delete :only_path
53         url << (options.delete(:protocol) || 'http')
54         url << '://' unless url.match("://") #dont add separator if its already been specified in :protocol 
55         
56         raise "Missing host to link to! Please provide :host parameter or set default_url_options[:host]" unless options[:host]
58         url << options.delete(:host)
59         url << ":#{options.delete(:port)}" if options.key?(:port)
60       else
61         # Delete the unused options to prevent their appearance in the query string
62         [:protocol, :host, :port].each { |k| options.delete k }
63       end
65       anchor = "##{CGI.escape options.delete(:anchor).to_param.to_s}" if options.key?(:anchor)
66       url << Routing::Routes.generate(options, {})
67       url << anchor if anchor
69       return url
70     end    
71   end
72   
73   # Rewrites URLs for Base.redirect_to and Base.url_for in the controller.
74   class UrlRewriter #:nodoc:
75     RESERVED_OPTIONS = [:anchor, :params, :only_path, :host, :protocol, :port, :trailing_slash, :skip_relative_url_root]
76     def initialize(request, parameters)
77       @request, @parameters = request, parameters
78     end
79     
80     def rewrite(options = {})
81       rewrite_url(options)
82     end
84     def to_str
85       "#{@request.protocol}, #{@request.host_with_port}, #{@request.path}, #{@parameters[:controller]}, #{@parameters[:action]}, #{@request.parameters.inspect}"
86     end
88     alias_method :to_s, :to_str
90     private
91       # Given a path and options, returns a rewritten URL string
92       def rewrite_url(options)
93         rewritten_url = ""
95         unless options[:only_path]
96           rewritten_url << (options[:protocol] || @request.protocol)
97           rewritten_url << "://" unless rewritten_url.match("://")
98           rewritten_url << rewrite_authentication(options)
99           rewritten_url << (options[:host] || @request.host_with_port)
100           rewritten_url << ":#{options.delete(:port)}" if options.key?(:port)
101         end
103         path = rewrite_path(options)
104         rewritten_url << @request.relative_url_root.to_s unless options[:skip_relative_url_root]
105         rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path)
106         rewritten_url << "##{options[:anchor]}" if options[:anchor]
108         rewritten_url
109       end
111       # Given a Hash of options, generates a route
112       def rewrite_path(options)
113         options = options.symbolize_keys
114         options.update(options[:params].symbolize_keys) if options[:params]
116         if (overwrite = options.delete(:overwrite_params))
117           options.update(@parameters.symbolize_keys)
118           options.update(overwrite.symbolize_keys)
119         end
121         RESERVED_OPTIONS.each { |k| options.delete(k) }
123         # Generates the query string, too
124         Routing::Routes.generate(options, @request.symbolized_path_parameters)
125       end
126       
127       def rewrite_authentication(options)
128         if options[:user] && options[:password]
129           "#{CGI.escape(options.delete(:user))}:#{CGI.escape(options.delete(:password))}@"
130         else
131           ""
132         end
133       end
134   end