REST on Rails之资源嵌套
REST认为一切都是资源(Resource),但并不是所有资源都是平行对等的,资源之间也有从属关系,要建立这种资源的层次关系,就必须将资源进行嵌套(nested resource)。
以Blog系统为例,假设每个用户拥有一个Profile,以及多个Blog,那么我们可以这样建立资源的嵌套关系,修改route.rb:
# profile
GET /users/1/profile = ProfilesController#show
GET /users/1/profile/new = ProfilesController#new
GET /users/1/profile/edit = ProfilesController#edit
POST /users/1/profile = ProfilesController#create
PUT /users/1/profile = ProfilesController#update
DELETE /users/1/profile = ProfilesController#destroy
# Blogs
GET /users/1/blogs = BlogsController#index
GET /users/1/blogs/1 = BlogsController#show
GET /users/1/blogs/1/edit = BlogsController#edit
GET /users/1/blogs/new = BlogsController#new
POST /users/1/blogs = BlogsController#create
PUT /users/1/blogs/1 = BlogsController#update
DELETE /users/1/blogs/1 = BlogsController#destroy
同时URL的Helper也需要进行相应的更改:
# profile
user_profile_path(1) /users/1/profile
new_user_profile_path(1) /users/1/profile/new
edit_user_profile_path(1) /users/1/profile/edit
# blogs
user_blogs_path(1) /users/1/blogs
user_blog_path(1, 1) /users/1/blogs/1
edit_user_blog_path(1, 1) /users/1/blogs/1/edit
new_user_blog_path(1) /users/1/blogs/new
另外如果你使用Edge Rails,那么针对user_blogs_path,你还可以简单的使用redirect_to:
redirect_to ([user, blog]) = /users/1/blogs/1
除了以上这些,new.html.erb和edit.html.erb中的form_for也必须做相应的修改:
#edit.html.erb
<%= form_for(:profile, {:html=>{:method =>:put}, :url=>user_profile_path(current_user)}) {|f| %>
这将生成:
<form action="/users/4/profile" method="post"><div style="margin:0;padding:0"><input name="_method" type="hidden" value="put" /></div>
注意这里的method必须是put,否则就会提交给ProfilesController#create,new.html.erb比较简单:
#new.html.erb
<% form_for(:profile, :url => user_profile_path(current_user)) do |f| %>
Blogs的new.html.erb和edit.html.erb可以依此类推,基本就这些了。