RESTfull design je přístup k programování webů který popisuje jakým způsobem se k jednotlivým objektům přistupuje. V podstatě logicky mapuje práci s jednotlivými objekty na url.
Pro přechod k REST budeme tedy měnit nejen řadič, ale také routy jenž k tomuto řadiči povedou.
Tabulka 47.5. RESTFull
standardní metody | sloveso | url | akce |
---|---|---|---|
plural _path | GET | /notes | index |
singular _path(id) | GET | /notes/1 | show |
new_singular _path | GET | /notes/new | new |
singular _path | POST | /notes | create |
edit_singular _path(id) | GET | /notes/1;edit | edit |
singular _path(id) | PUT | /notes/1 | update |
singular _path(id) | DELETE | /notes/1 | destroy |
# GET /notes # GET /notes.xml # ... def index @notes = Note.find(:all) respond_to do |format| format.html # index.html.erb format.xml { render :xml => @notes.to_xml } format.rss { render :xml => @notes.to_rss } end end
Příklad 47.24. Controller Template
class MyController < ApplicationController # GET /notes # GET /notes.xml def index @notes = Note.find(:all) respond_to do |format| format.html # index.html.erb format.xml { render :xml => @notes.to_xml } end end # GET /notes/1 # GET /notes/1.xml def show @note = Note.find(params[:id]) respond_to do |format| format.html # index.html.erb format.xml { render :xml => @notes.to_xml } end end # GET /notes/new def new @mode = 'new' @note = Note.new end def create @note = Note.create(params_hash) respond_to do |wants| wants.html {redirect_to :action=>:index} wants.js {render} end end def edit @note = Note.find(params[:id]) end def update object = @note, … if Note.update_attributes(params_hash) respond_to do |wants| wants.html {redirect_to :action=>:index} wants.js {render} end else render end end def destroy … end end
Routes
ActionController::Routing::Routes.draw do |map| map.resources :notes, :sessions end
V pohledu index.html.erb
<h1>Přehled poznámek</h1> <table> <tr></tr> <% for note in @notes %> <tr> <td></td> <td><%= link_to 'Show', note_path(note) %></td> <td><%= link_to 'Edit', edit_note_path(note) %></td> <td><%= link_to 'Destroy', note_path(note), :confirm => 'Are you sure?', :method => :delete %></td> </tr> <% end %> </table> <br/> <%= link_to 'Nová poznámka'm new_note_path %>
Místo odkazů link_to
můžeme používat tlačítka button_to
. Je třeba vědět, že tlačítka tako vytvářená sebou "nesou" celý formulář. Pokud chceme použít AJAX, budou uvedené řádky vypadat
<td><%= link_to_remote 'Destroy', :url => note_path(note), :confirm => 'Are you sure?', :method => :delete %></td>
Řadič k mazání záznamů (metoda destroy
)
# DELETE /notes/1 # DELETE /notes/1.xml def destroy @note = Note.find(params[:id]) @note.destroy respond_to do |format| format.html { redirect_to notes_url } # go to index format.js # run the destroy.rjs template format.xml { render :nothing = > true } end end
Smazání poznámky z konzole
$
curl -X DELETE -H "Accept: text/xml" http://localhost:3000/notes/2
$
curl -X DELETE -H "Accept: application/javascript" http://localhost:3000/notes/2
Ošetření chyb. Tedy pokoušíme se smazat něco co již neexistuje
# DELETE /notes/1 # DELETE /notes/1.xml def destroy @note = Note.find(params[:id]) @note.destroy respond_to do |format| format.html { redirect_to notes_url } # go to index format.js # run the destroy.rjs template format.xml { render :nothing = > true } end rescue Exception => e respond_to do |format| format.html { render :text => "Record not found", status => 404 } format.js { render(:update) {|page| page.alert("There was an error")}} format.xml { render :nothing = > true, :status => 404 } end end
K editaci potřebujeme pohled edit.html.erb
<h1>Editace poznámky</h1> <% form_for(:note, :url => note_path(@note), :html => { :method => :put }) do |f| %> <label for="">Title <%= f.text_field :title, :class => 'text_field' %> </label> <label for="">Content <%= f.text_area :content %> </label> # nebo výš uvedená pole formuláře umístníme do samsotatného souboru _form.hmtl.erb # a zde jen uvedeme partial <%= render :partial => 'form', :locals => {:f => f} %> <p><%= submit_tag "Update" %></p> <% end %> <% link_to 'Show', note_path(@note) %> | <% link_to 'Back', notes_path %>
Pohled pro vytváření novoho záznamu:
<h1>Nová poznámka</h1> <% form_for(:note, :url => notes_path) do |f| %> <%= render :partial => 'form', :locals => {:f => f} %> <p><%= submit_tag "Create" %></p> <% end %> <% link_to 'Back', notes_path %>
$ script/plugin install http://dev.rubyonrails.org/svn/rails/plugins/simply_helpful/
Formáty použité v respond_to do |format|
můžeme rozšířit o vlastní formát. V souboru environment.rb
zaragistrujeme mime typ.
Mime::Type.register 'application/vnd.blinksale+xml', :api Mime::Type.register 'application/vnd.visa+xml, :visa
Máme-li model s relací one_to_many, potřebujeme naprogramovat aplikaci tak, aby v rámci RESTFull principu "rozuměla" url jako:
/notes/1/keywords/6
Příklad 47.25. routes.rb pro vnořenou tabulku /notes/:note_id/keywords/:id
ActionController::Routing::Routes.draw do |map| … # /notes/:note_id/keywords/:id map.resources :notes do |notes| notes.resources :keywords, :name_prefix => 'note_' end map.resources :keywords