Ruby on Rails 2.0 日记
第6章 redirect_to 与 url_for
这一章关于 redirect_to 方法与 url_for 方法。与 REST 相关的一些话题。
首先,做个简单的 User 模型的 scaffold。
ruby script/generate scaffold user name:string
app/controllers/users_controller.rb 的 create 选项如下。
# POST /users
# POST /users.xml
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
flash[:notice] = 'User was successfully created.'
format.html { redirect_to(@user) }
format.xml { render :xml => @user, :status => :created, :location => @user }
else
format.html { render :action => "new" }
format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
end
end
end
注意format.html { redirect_to(@user) } 这一行。对象 ActiveRecord 被发送到 redirect_to 参数。Rails 1.2.x 中这样的写法是不可以的。要这样做的话,必须写 format.html { redirect_to user_url(@user) } 。这就是进步啊。
来看看 Rails 的源代码。
首先从Rails 1.2.6 (actionpack-1.13.6) 的代码开始。
def redirect_to(options = {}, *parameters_for_method_reference) #:doc:
case options
when %r{^\w+://.*}
# (省略)
when String
# (省略)
when :back
# (省略)
else
if parameters_for_method_reference.empty?
redirect_to(url_for(options))
response.redirected_to = options
else
# (省略)
end
end
end
将对象 ActiveRecord 发送到参数的情况下,执行redirect_to(url_for(options)) 。但是,Rails 1.2.6 的 url_for 方法不能处理 ActiveRecord 对象。
接下来是 Rails 2.0.2 (actionpack-2.0.2) 的代码。
def redirect_to(options = {}, response_status = {}) #:doc:
# (省略)
case options
when %r{^\w+://.*}
# (省略)
when String
# (省略)
when :back
# (省略)
when Hash
# (省略)
else
redirect_to(url_for(options), :status=>status)
end
end
把对象 ActiveRecord 发送到参数的情况下,执行最后的 redirect_to(url_for(options), :status=>status) 。通过 url_for 方法生成 URL。
那么让我们看看 url_for 方法。
def url_for(options = nil) #:doc:
case options || {}
when String
options
when Hash
@url.rewrite(rewrite_options(options))
else
polymorphic_url(options)
end
end
因为 ActiveRecord 对象被发送到参数 options ,所以 else 块的 polymorphic_url(options) 被执行。
定义这个方法的是 polymorphic_routes.rb 。
def polymorphic_url(record_or_hash_or_array, options = {})
# (省略)
named_route = build_named_route_call(record_or_hash_or_array, namespace, inflection, options)
send!(named_route, *args)
end
下面第3行的 build_named_route_call 方法,返回'user_url' 字符串。为了将 redirect_to user_url(@user) 缩短为 redirect_to(@user) ,很费了一番功夫。大家辛苦了!
(2008/02/24)
- 前言
- 第1章 安装 (2007/12/15)
- 第2章 生成新程序 (2007/12/16)
- 第3章 SQLite3 (2007/12/21)
- 第4章 模板文件的扩展名 (2007/12/22)
- 第5章 功能测试 (2008/01/19)
- 第6章 redirect_to 与 url_for (2008/02/24)
- 第7章 config/initializers 目录 (2008/02/27)
- 第8章 生成 Rails 1.2 的 API 文档 (2008/03/04)
- 第9章 helper :all (2008/05/05)

