Skip to content

Commit c98692a

Browse files
Clemens Koflerjosh
authored andcommitted
Removed handling of string parameter in link_to to have all URL generation done by url_for
Signed-off-by: Joshua Peek <josh@joshpeek.com>
1 parent 938caf4 commit c98692a

File tree

2 files changed

+60
-44
lines changed

2 files changed

+60
-44
lines changed

actionpack/lib/action_view/helpers/url_helper.rb

Lines changed: 50 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
module ActionView
44
module Helpers #:nodoc:
55
# Provides a set of methods for making links and getting URLs that
6-
# depend on the routing subsystem (see ActionController::Routing).
7-
# This allows you to use the same format for links in views
6+
# depend on the routing subsystem (see ActionController::Routing).
7+
# This allows you to use the same format for links in views
88
# and controllers.
99
module UrlHelper
1010
include JavaScriptHelper
@@ -33,8 +33,8 @@ module UrlHelper
3333
#
3434
# If you instead of a hash pass a record (like an Active Record or Active Resource) as the options parameter,
3535
# you'll trigger the named route for that record. The lookup will happen on the name of the class. So passing
36-
# a Workshop object will attempt to use the workshop_path route. If you have a nested route, such as
37-
# admin_workshop_path you'll have to call that explicitly (it's impossible for url_for to guess that route).
36+
# a Workshop object will attempt to use the workshop_path route. If you have a nested route, such as
37+
# admin_workshop_path you'll have to call that explicitly (it's impossible for url_for to guess that route).
3838
#
3939
# ==== Examples
4040
# <%= url_for(:action => 'index') %>
@@ -62,19 +62,33 @@ module UrlHelper
6262
# <%= url_for(@workshop) %>
6363
# # calls @workshop.to_s
6464
# # => /workshops/5
65+
#
66+
# <%= url_for("http://www.example.com") %>
67+
# # => http://www.example.com
68+
#
69+
# <%= url_for(:back) %>
70+
# # if request.env["HTTP_REFERER"] is set to "http://www.example.com"
71+
# # => http://www.example.com
72+
#
73+
# <%= url_for(:back) %>
74+
# # if request.env["HTTP_REFERER"] is not set or is blank
75+
# # => javascript:history.back()
6576
def url_for(options = {})
6677
options ||= {}
67-
case options
78+
url = case options
79+
when String
80+
escape = true
81+
options
6882
when Hash
6983
options = { :only_path => options[:host].nil? }.update(options.symbolize_keys)
7084
escape = options.key?(:escape) ? options.delete(:escape) : true
71-
url = @controller.send(:url_for, options)
72-
when String
73-
escape = true
74-
url = options
85+
@controller.send(:url_for, options)
86+
when :back
87+
escape = false
88+
@controller.request.env["HTTP_REFERER"] || 'javascript:history.back()'
7589
else
7690
escape = false
77-
url = polymorphic_path(options)
91+
polymorphic_path(options)
7892
end
7993

8094
escape ? escape_once(url) : url
@@ -116,8 +130,8 @@ def url_for(options = {})
116130
#
117131
# Note that if the user has JavaScript disabled, the request will fall back
118132
# to using GET. If <tt>:href => '#'</tt> is used and the user has JavaScript disabled
119-
# clicking the link will have no effect. If you are relying on the POST
120-
# behavior, your should check for it in your controller's action by using the
133+
# clicking the link will have no effect. If you are relying on the POST
134+
# behavior, your should check for it in your controller's action by using the
121135
# request object's methods for <tt>post?</tt>, <tt>delete?</tt> or <tt>put?</tt>.
122136
#
123137
# You can mix and match the +html_options+ with the exception of
@@ -141,8 +155,8 @@ def url_for(options = {})
141155
#
142156
# link_to "Profile", :controller => "profiles", :action => "show", :id => @profile
143157
# # => <a href="/profiles/show/1">Profile</a>
144-
#
145-
# Similarly,
158+
#
159+
# Similarly,
146160
#
147161
# link_to "Profiles", profiles_path
148162
# # => <a href="/profiles">Profiles</a>
@@ -197,9 +211,9 @@ def url_for(options = {})
197211
# # => <a href="/images/9" onclick="window.open(this.href,'new_window_name','height=300,width=600');return false;">View Image</a>
198212
#
199213
# link_to "Delete Image", @image, :confirm => "Are you sure?", :method => :delete
200-
# # => <a href="/images/9" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form');
214+
# # => <a href="/images/9" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form');
201215
# f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;
202-
# var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method');
216+
# var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method');
203217
# m.setAttribute('value', 'delete'); f.appendChild(m);f.submit(); };return false;">Delete Image</a>
204218
def link_to(*args, &block)
205219
if block_given?
@@ -211,14 +225,7 @@ def link_to(*args, &block)
211225
options = args.second || {}
212226
html_options = args.third
213227

214-
url = case options
215-
when String
216-
options
217-
when :back
218-
@controller.request.env["HTTP_REFERER"] || 'javascript:history.back()'
219-
else
220-
self.url_for(options)
221-
end
228+
url = url_for(options)
222229

223230
if html_options
224231
html_options = html_options.stringify_keys
@@ -228,7 +235,7 @@ def link_to(*args, &block)
228235
else
229236
tag_options = nil
230237
end
231-
238+
232239
href_attr = "href=\"#{url}\"" unless href
233240
"<a #{href_attr}#{tag_options}>#{name || url}</a>"
234241
end
@@ -260,7 +267,7 @@ def link_to(*args, &block)
260267
# * <tt>:confirm</tt> - This will add a JavaScript confirm
261268
# prompt with the question specified. If the user accepts, the link is
262269
# processed normally, otherwise no action is taken.
263-
#
270+
#
264271
# ==== Examples
265272
# <%= button_to "New", :action => "new" %>
266273
# # => "<form method="post" action="/controller/new" class="button-to">
@@ -286,12 +293,12 @@ def button_to(name, options = {}, html_options = {})
286293
end
287294

288295
form_method = method.to_s == 'get' ? 'get' : 'post'
289-
296+
290297
request_token_tag = ''
291298
if form_method == 'post' && protect_against_forgery?
292299
request_token_tag = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
293300
end
294-
301+
295302
if confirm = html_options.delete("confirm")
296303
html_options["onclick"] = "return #{confirm_javascript_function(confirm)};"
297304
end
@@ -309,7 +316,7 @@ def button_to(name, options = {}, html_options = {})
309316
# Creates a link tag of the given +name+ using a URL created by the set of
310317
# +options+ unless the current request URI is the same as the links, in
311318
# which case only the name is returned (or the given block is yielded, if
312-
# one exists). You can give link_to_unless_current a block which will
319+
# one exists). You can give link_to_unless_current a block which will
313320
# specialize the default behavior (e.g., show a "Start Here" link rather
314321
# than the link's text).
315322
#
@@ -336,13 +343,13 @@ def button_to(name, options = {}, html_options = {})
336343
# </ul>
337344
#
338345
# The implicit block given to link_to_unless_current is evaluated if the current
339-
# action is the action given. So, if we had a comments page and wanted to render a
346+
# action is the action given. So, if we had a comments page and wanted to render a
340347
# "Go Back" link instead of a link to the comments page, we could do something like this...
341-
#
342-
# <%=
348+
#
349+
# <%=
343350
# link_to_unless_current("Comment", { :controller => 'comments', :action => 'new}) do
344-
# link_to("Go back", { :controller => 'posts', :action => 'index' })
345-
# end
351+
# link_to("Go back", { :controller => 'posts', :action => 'index' })
352+
# end
346353
# %>
347354
def link_to_unless_current(name, options = {}, html_options = {}, &block)
348355
link_to_unless current_page?(options), name, options, html_options, &block
@@ -359,10 +366,10 @@ def link_to_unless_current(name, options = {}, html_options = {}, &block)
359366
# # If the user is logged in...
360367
# # => <a href="/controller/reply/">Reply</a>
361368
#
362-
# <%=
369+
# <%=
363370
# link_to_unless(@current_user.nil?, "Reply", { :action => "reply" }) do |name|
364371
# link_to(name, { :controller => "accounts", :action => "signup" })
365-
# end
372+
# end
366373
# %>
367374
# # If the user is logged in...
368375
# # => <a href="/controller/reply/">Reply</a>
@@ -391,10 +398,10 @@ def link_to_unless(condition, name, options = {}, html_options = {}, &block)
391398
# # If the user isn't logged in...
392399
# # => <a href="/sessions/new/">Login</a>
393400
#
394-
# <%=
401+
# <%=
395402
# link_to_if(@current_user.nil?, "Login", { :controller => "sessions", :action => "new" }) do
396403
# link_to(@current_user.login, { :controller => "accounts", :action => "show", :id => @current_user })
397-
# end
404+
# end
398405
# %>
399406
# # If the user isn't logged in...
400407
# # => <a href="/sessions/new/">Login</a>
@@ -431,20 +438,20 @@ def link_to_if(condition, name, options = {}, html_options = {}, &block)
431438
# * <tt>:bcc</tt> - Blind Carbon Copy additional recipients on the email.
432439
#
433440
# ==== Examples
434-
# mail_to "me@domain.com"
441+
# mail_to "me@domain.com"
435442
# # => <a href="mailto:me@domain.com">me@domain.com</a>
436443
#
437-
# mail_to "me@domain.com", "My email", :encode => "javascript"
444+
# mail_to "me@domain.com", "My email", :encode => "javascript"
438445
# # => <script type="text/javascript">eval(unescape('%64%6f%63...%6d%65%6e'))</script>
439446
#
440-
# mail_to "me@domain.com", "My email", :encode => "hex"
447+
# mail_to "me@domain.com", "My email", :encode => "hex"
441448
# # => <a href="mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">My email</a>
442449
#
443-
# mail_to "me@domain.com", nil, :replace_at => "_at_", :replace_dot => "_dot_", :class => "email"
450+
# mail_to "me@domain.com", nil, :replace_at => "_at_", :replace_dot => "_dot_", :class => "email"
444451
# # => <a href="mailto:me@domain.com" class="email">me_at_domain_dot_com</a>
445452
#
446453
# mail_to "me@domain.com", "My email", :cc => "ccaddress@domain.com",
447-
# :subject => "This is an example email"
454+
# :subject => "This is an example email"
448455
# # => <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">My email</a>
449456
def mail_to(email_address, name = nil, html_options = {})
450457
html_options = html_options.stringify_keys

actionpack/test/template/url_helper_test.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ def test_url_for_escapes_url_once
2828
assert_equal "http://www.example.com?a=b&amp;c=d", url_for("http://www.example.com?a=b&amp;c=d")
2929
end
3030

31+
def test_url_for_with_back
32+
@controller.request = RequestMock.new("http://www.example.com/weblog/show", nil, nil, {'HTTP_REFERER' => 'http://www.example.com/referer'})
33+
assert_equal 'http://www.example.com/referer', url_for(:back)
34+
end
35+
36+
def test_url_for_with_back_and_no_referer
37+
@controller.request = RequestMock.new("http://www.example.com/weblog/show", nil, nil, {})
38+
assert_equal 'javascript:history.back()', url_for(:back)
39+
end
40+
3141
# todo: missing test cases
3242
def test_button_to_with_straight_url
3343
assert_dom_equal "<form method=\"post\" action=\"http://www.example.com\" class=\"button-to\"><div><input type=\"submit\" value=\"Hello\" /></div></form>", button_to("Hello", "http://www.example.com")
@@ -419,7 +429,6 @@ def with_restful_routing
419429
end
420430
end
421431

422-
423432
class Workshop
424433
attr_accessor :id, :new_record
425434

0 commit comments

Comments
 (0)