url_for之疑问

在控制器中,我们经常要实现这样的功能:如果未登录时访问action A,则该过滤器自动将请求重定向到登录页,登录之后将参数原封不动地再传递给action A。可以使用下列代码简单地实现这个重定向:

1
redirect_to :controller => '/accounts/login', :continue => url_for(params)

其中continue参数表示,登录之后需要回调的地址。

但有这样的一种情况:如果需要点击某个链接而不是直接重定向去登录,登录后再通过continue值将原参数返回到原始action中。用上面方法实现时,你就会发现参数传递错误,如下面的实现方式都是错误的:

1
2
3
4
5
参数会被截断:
<a href="<%="#{home}/signin?f=1&continue=#{url_for(params)}"%>">example</a>
 
参数传递错误,在浏览器地址栏中会出现诸如&amp;continue=xxx
<a href="<%="#{home}/signin?continue=#{URI.encode(url_for(params), /[&:\/]/)}"%>">example</a>

查看了生成链接的源代码,发现url_for(params)生成的链接会将url中参数的连接符&转成&amp;符号,而正确的转换应是%26。因此在使用encode编码url_for字符串之前,需要先转换url中的HTML实体:

1
2
3
4
5
6
7
8
9
10
11
# 在irb中转换字符串的HTML实体示例
require 'cgi'
require "erb"
include ERB::Util
 
str='a=1&amp;b=2'
str1 = CGI.unescapeHTML(str) # output:a=1&b=2
str2 = ERB::Util.html_escape(str1)  #output:a=1&amp;b=2
 
CGI.unescapeHTML '&'          # 输出 &
CGI.unescapeHTML '&amp;'    # 输出 &

因此,最终实现如下:

1
2
3
4
5
<%
continue = "#{@config['home']}#{CGI.unescapeHTML(url_for(params))}"  # 关键
continue = URI.encode(continue, /[&:\/]/)
%>
<a href="<%="#{home}/signin?f=1&continue=#{continue}"%>">example</a>

还有要注意的是,在action中使用params[:continue]时不需要再用URI.deconde解码了,rails会自动转换%26为&符号。

使用Escape, Unescape, Encode, Decode, HTML, XML, URI, URL的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
require 'cgi'
 
# escape
name = "ruby?"
value = "yes"
url = "http://example.com/?" + CGI.escape(name) + '=' + CGI.escape(value) + "&var=T"
# url: http://example.com/?ruby%3F=yes&var=T
html = %(<a href="#{CGI.escapeHTML(url)}">example</a>)
# html: <a href="http://example.com/?ruby%3F=yes&amp;var=T">example</a>
 
# unescape
name_encoded = html.match(/http:([^"]+)/)[0]
# name_encoded: http://example.com/?ruby%3F=yes&amp;var=T
href = CGI.unescapeHTML(name_encoded)
# href: http://example.com/?ruby%3F=yes&var=T
query = href.match(/\?(.*)$/)[1]
# query: ruby%3F=yes&var=T
pairs = query.split('&')
# pairs: ["ruby%3F=yes", "var=T"]
name, value = pairs[0].split('=').map{|v| CGI.unescape(v)}
# name, value: ["ruby?", "yes"]

Monitor Your Web Site 24/7 - Receive email and SMS alerts anytime your web site goes down.

Related Posts

Leave a Reply

Monitor Your Web Site 24/7 - Receive email and SMS alerts anytime your web site goes down.

About Me

About Me
Record Technical Articles at Gooss.org.

Entries (RSS) and Comments (RSS). Valid XHTML and CSS and XFN.

© Copyright 2009 山海经. All rights reserved.

Social Bookmarks

Copyright © Designed by: Free WP Templates
Food Charts |  About Breast Milk |  Organic Food