在前面的博文中,介绍了简单的CRUD风格的实现。
接下来我们在此基础上来实现一下RESTful版本的CRUD。
为什么要采用RESTful风格:designing controller and action is chaos
HTTP methods (RFC 2616)
POST -> Create
GET -> Read
PUT -> Update
DELETE -> Delete
Remove actions from URL, and we have simple named route.
/events/create -> POST /events
/events/show/1 -> GET /events/1
/events/update/1 -> PUT /events/1
/events/destroy/1 -> DELETE /events/1
CRUD-based action names get things simpler
create -> POST
show -> GET
PUT -> update
delete -> DELETE
尽量每一个controller值负责一组CRUD
下面开始实施
自动建立一组named routes对应到actions
編輯 /config/routes.rb,加入
map.resources :events
编辑/app/views/events/index.html.erb
<ul><%= will_paginate @events %><% @events.each do |event| %><li><%= link_to event.name, event_path(event) %><%= link_to 'edit', edit_event_path(event) %><%= link_to 'delete', event_path(event), :method => :delete %></li><% end -%><%= will_paginate @events %> </ul> <%= link_to 'new event', :controller => 'events', :action => 'new' %>
event_path的默认请求方法是 GET
对比一下原有的souce
<ul><%= will_paginate @events %><% @events.each do |event| %><li> <%= link_to event.name, :controller => 'events', :action => 'show', :id => event %><%= link_to 'edit', :controller => 'events', :action => 'edit', :id => event %><%= link_to 'delete', :controller => 'events', :action => 'destroy', :id => event %></li><% end -%><%= will_paginate @events %> </ul> <%= link_to 'new event', :controller => 'events', :action => 'new' %>
编辑/app/views/events/show.html.erb
<%=h @event.name %> <%=h @event.description %> <p><%= link_to 'back to index', events_path %> </p>
编辑/app/views/events/new.html.erb
<%= error_messages_for :event %> <% form_for @event, :url => events_path do |f| %> <%= render :partial => 'form', :locals => { :f => f } %> <%= f.submit "Create" %> <% end %>
在Form中events_path的默认请求方法是POST
编辑/app/views/events/edit.html.erb
<%= error_messages_for :event %> <% form_for @event, :url => event_path(@event), :html => { :method => :put } do |f| %> <%= render :partial => 'form', :locals => { :f => f } %> <%= f.submit "Update" %> <% end %>
运行一下看看吧~
总结一下HTTP请求跟action的4-7关系表:
其实HTML规格只支持GET/POST,不支持PUT和DELETE方法的,rails在生成HTML的时候偷偷的做了一些处理。
我们写的代码是这样的:
<%##event_path默认是GET,删除需要指定:method##%><%= link_to 'delete', event_path(event), :method => :delete %>
生成的HTML是这样的:
<a οnclick="var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'TwKvS1qYjCaO2RQ3QlCdo3K57NfH0yTqKShmMk8jjI0='); f.appendChild(s);f.submit();return false;" href="/events/1">delete</a>
当点击的时候,实际上在页面上生成了下面内容:
<form id="edit_events_1" method="post" action="/events/1"> <input type="hidden" value="put" name="_method"/> .... </form>
其实各种浏览器之间还有一些关于DELETE和PUT一些支持或者不支持的不统一现象,这些问题Rails处理掉了,我们不需要关注了。
另外,XmlHttpRequest(Ajax request)定义了GET/POST/PUT/DELETE/HEAD/OPTIONS
不过不是所有浏览器都支持。