xmlhack.ru logo
>> статьи на xmlhack.ru

Установка REST на Rails

Автор: Дэн Куб
Перевод: Кондаков Валерий
Опубликовано на XML.com (19.04.2006, англ.): http://www.xml.com/pub/a/2006/04/19/rest-on-rails.html
Опубликовано на xmlhack.ru (22.06.2006, рус.): http://xmlhack.ru/texts/06/rest-on-rails/rest-on-rails.html
В закладки:   Del.icio.us   reddit

Координация в Rails с использованием REST

«Соглашения по конфигурации» — один из ключевых принципов, стоящих в основе Ruby on Rails. Он разрабатывался довольно специфическим образом, и, если вы будете следовать «пути Rails», всё будет работать вообще без настроек или с минимальными настройками. Вот почему Rails так популярна — если вы действуете согласно соглашений, то получите множество преимуществ, прикладывая меньше усилий, чем потребовалось бы при использовании иных объектных структур.

В этом отношении можно провести параллели с протоколом HTTP. Стоит только отойти от основного пути, как окажется, что вы пытаетесь подобрать замену тем основным вещам, которые совершенно свободно предоставляет сам HTTP. Оставайтесь на пути и получите все преимущества, как, к примеру, кэширование и прекрасную масштабируемость приложений меньшими усилиями. Хорошо спроектированное — что обычно означает использование REST — веб-приложение должно правильно использовать доступные методы HTTP, а не полагаться на запросы GET, чтобы изменять состояния сервера.

Идеал состоит в том, чтобы обратиться к другому оператору, основанному на методе HTTP (на самом деле исполняющему иной код в зависимости от метода), и сделать невозможным непреднамеренное изменение состояния с помощью запроса GET.

Rails для REST

Дело в том, что разработчики даже и не думают о HTTP просто потому, что до недавнего времени он не являлся объектом обсуждения подавляющего большинства разработчиков. И это обычное явление, что разработчик многого не знает о REST и HTTP, или не знает, почему они так важны. Но что, если эти соглашения были приняты в Rails, который постепенно подталкивает разработчиков на путь, облегчающий разработку приложений на REST?

Учитывая все это, я решил разработать плагин Rails для REST (RESTful Rails plugin), который бы облегчил создание REST-приложений в Rails. Проект был вдохновлен статьёй On HTTP Abuse, которая описывала возможности HTTP, не вполне поддерживаемые большинством объектных структур. Моя основная цель в том, чтобы обеспечить поддержку возможностям, которые ещё не включены в Rails, и, вместе с тем, минимально повлиять на путь разработки приложений в Rails.

Чему вы научитесь

В этой статье описывается очень простое приложение, использующее RESTful Rails plugin. Чтобы следовать статье, понадобится установить последнюю версию Rails (1.1.1. на момент написания статьи), а также любую базу данных. Я также предполагаю наличие некоторых основных знаний о том, как сконфигурировать выбранную базу данных для использования Rails, используя config/database.yml. Также понадобится установить клиент Subversion, поскольку он потребуется для установки RESTful Rails plugin.

Для разрешения любых вопросов привожу ссылки на несколько прекрасных туториалов:

Если Rails уже установлен, можно произвести апгрейд до последней версии с помощью следующей команды:

gem install rails --include-dependencies

Потребуется как минимум версия Rails 1.1.1, чтобы следовать данной статье, поскольку некоторые из возможностей до недавнего времени не поддерживались.

Приступая к работе

Начну с описания примера, который будем использовать, простой проги, предназначенной для обработки личной книжной библиотеки. Чтобы создать проект Rails, введите следующее в командной строке:

rails --database=mysql library

Пожалуйста, обратите внимание, что опция --database=mysql заставляет Rails переконфигурировать config/database.yml для использования баз MySQL. Аналогично можно воспользоваться любым из следующих параметров:

Откроем директорию library, которая была только что создана для этого проекта:

cd library

Модель

Чтобы в данном примере нас ничто не отвлекало от REST, создадим модель Book только с двумя атрибутами ( title и description), а также не будем обрабатывать ошибки, как вы бы, конечно же, сделали в настоящей проге.

Чтобы создать модель Book, введём следующее в командной строке:

ruby script/generate model Book

Проверим новую модель, запустив тест её юнитов:

rake test:units

Вы увидите несколько ошибок, поскольку нам требуется сообщить Rails, как именно следует подключаться к базе данных.

Конфигурация базы данных

Я использую MySQL, однако, вы можете использовать любую базу данных, поддерживаемую Rails. Откройте config/database.yml и измените его, чтобы можно было работать с конфигурацией вашей базы данных.

В моём случае config/database.yml выглядит следующим образом:

development:
  adapter: mysql
  database: library_development
  username: root
  password:
  host: localhost
  socket: /usr/local/mysql/run/mysql_socket

test:
  adapter: mysql
  database: library_test
  username: root
  password:
  host: localhost
  socket: /usr/local/mysql/run/mysql_socket

production:
  adapter: mysql
  database: library_production
  username: root
  password:
  host: localhost
  socket: /usr/local/mysql/run/mysql_socket

Обратите внимание, что я запускаю этот пример на тестовом сервере базы данных на локальной машине. В системе производства вы не захотите использовать учетную запись администратора. Единственное требование Rails состоит в том, что пользователь должен иметь возможность использовать команды CREATE и DROP для работы с таблицами и указателями в дополнение к стандартным командам SQL: SELECT, INSERT, UPDATE и DELETE.

Также убедитесь, что вы создали базы, перечисленные в config/database.yml, используя способ, подходящий для вашей базы данных. В моём случае я ввёл следующие команды для создания баз:

mysqladmin -u root create library_development
mysqladmin -u root create library_test
mysqladmin -u root create library_production

Команда rake test:units все ещё должна выдавать ошибку, поскольку мы не создали таблицу для книг.

Перемещение баз данных

Нам потребуется добавить таблицу для книг в разрабатываемую базу данных. Для этого воспользуемся системой перемещения Rails, которая позволяет определить способ, независящий от типа базы данных. Как только система перемещения будет запущена, она определит текущую версию схемы базы и обновит её до самой последней версии.

Начиная с версии Rails 1.1, всякий раз, как вы создаёте новую модель, скрипт перемещения будет создан для неё автоматически. В нашем случае скриптом перемещения для Book является db/migrate/001_create_books.rb. Обновите этот файл, чтобы он стал выглядеть следующим образом:

class CreateBooks < ActiveRecord::Migration
  def self.up
    create_table :books do |t|
      t.column :title, :string, :limit => 30, :null => false
      t.column :description, :text
    end
  end

  def self.down
    drop_table :books
  end
end

Это добавит в таблицу books две колонки: title и description.

Теперь запустим перемещение:

rake db:migrate

Это обновит базу development в config/database.yml и добавит таблицу books.

Теперь команда rake test:units будет выполнена без ошибок!

Далее в данной статье мы будем пребывать либо в состоянии “all-tests passing state”; («все тесты проходят») , либо “failing state” («есть ошибки»). Мы будем перемещаться между этими двумя состояниями, как только приложение начнёт приобретать более отчётливые очертания.

Вспомогательная система для тестирования

До того, как мы погрузимся в работу с контроллером, нам потребуется тестовая информация, чтобы было с чем работать. Воспользуемся вспомогательной системой, чтобы загружать записи в тестовую базу данных каждый раз, когда будет запускаться тест юнита или функциональный тест.

Первым делом нам следует создать тест юнита, чтобы убедиться, что вспомогательная система содержит нужную информацию. Замените метод test_truth, содержащийся в test/unit/book_test.rb по умолчанию, на следующее:

def test_fixture
  assert_kind_of Book, books(:http_book)
  assert_valid books(:http_book)
  assert_equal 1, Book.count
end

Метод проверит, что в вспомогательной системе присутствует корректная запись :http_book и при том в единственном экземпляре. Если по какой-то причине запись :http_book не будет обнаружена, или таких записей будет больше одной, тест юнита выдаст ошибку.

Команда rake test:units выдаст ошибку, поскольку мы ещё не сконфигурировали вспомогательную систему.

Rails автоматически создает наполнение для test/fixtures/books.yml вспомогательной системы при создании модели Book. Обновите этот файл, чтобы он стал выглядеть следующим образом:

http_book:
  id:          1
  title:       "HTTP: The Definitive Guide"
  description: "Everything that technical people need for using HTTP efficiently."

Теперь команда rake test:units должна выполниться без ошибок.

Теперь мы можем быть совершенно уверены, что модель Book и её наполнение могут быть использованы в дальнейшей работе, так что перейдём к контроллеру, однако, сперва нам потребуется установить RESTful Rails plugin.

RESTful Rails Plugin

RESTful Rails plugin добавляет к стандартным контроллерам Rails несколько возможностей, которые позволяют более эффективно использовать HTTP. В основе нашего примера самое очевидное достоинство плагина: метод координации через HTTP. С ним у вас появится возможность исполнять различный код в зависимости от метода запроса HTTP. Неплохое дополнительное преимущество состоит в том, что метод также берёт на себя обработку метода OPTIONS, который нам понадобится в тестах.

Чтобы установить плагин, введите следующее в командную строку:


svn co svn://rubyforge.org/var/svn/restful-rails/trunk
vendor/plugins/restful-rails

Или же, если ваш проект использует контроль версий с помощью Subversion, установите его, используя систему плагина Rails:


ruby script/plugin install -x svn://rubyforge.org/var/svn/restful-rails/trunk

Обе эти команды могут создавать снимок последнего состояния RESTful Rails plugin и помещать его в директорию vendor/plugins/restful-rails/.

Теперь, поскольку плагин установлен, создадим контроллер.

Контроллер

Чтобы создать контроллер BookController введите следующую команду:

ruby script/generate controller Book

Протестируем контроллер, запустив тесты функциональности:

rake test:functionals

Это должно пройти без ошибок.

Маршруты Rest

Контроллер BookController должен обрабатывать запросы на два URI:

/books/ Собрание книг
/books/{id} Книга, идентифицируемая по ID

Проверим, правильно ли обрабатываются URI.

Замените стандартный метод test_truth в test/functional/book_controller_test.rb следующим кодом:

def test_routing
  with_options :controller => 'book' do |test|
    test.assert_routing 'books',   :action => 'collection'
    test.assert_routing 'books/1', :action => 'by_id', :id => '1'
  end
end

Это проверит, что URI ведут к правильному контроллеру и действию. Обратите внимание на использование нового метода with_options, который уменьшит ввод, позволив вам определить опции по умолчанию для всех методов блока.

Команда rake test:functionals должна выдать ошибку, поскольку мы ещё не настроили, как URI должны вести к контроллерам.

Чтобы настроить маршрутизацию, нам требуется добавить в блок ActionController::Routing::Routes.draw внутри config/routes.rb следующую строчку:

map.connect_resource :book

Метод connect_resource берётся из RESTful Rails plugin и настраивает маршруты, которые подходят к требуемой структуре URI.

Команда rake test:functionals теперь должна выполниться без ошибок.

Теперь, когда маршрутизация настроена, перейдём к контроллеру.

Создание контроллера REST

В данный момент контроллер даже не подозревает о RESTful Rails plugin. Чтобы добавить координацию методов и другие возможности, необходимо вставить RestController::Base в самое начало app/controllers/book_controller.rb следующим образом:

class BookController < ApplicationController
  include RestController::Base
end

Теперь всё готово, чтобы добавить ресурс :collection в контроллер.

Ресурс collection

Ресурс :collection представляет собой список книг. Нам нужна возможность просматривать список с помощью метода GET и пополнять список, используя POST. Добавим в test/functional/book_controller_test.rb тест, чтобы убедиться, что эти методы поддерживаются:

def test_options_collection
  options :collection
  assert_response HTTP::Status::NO_CONTENT
  assert_no_entity
  assert_allowed_methods :get, :post
end

С помощью этого происходит проверка, что при выполнении запроса OPTIONS для :collection, возвращается код состояния 204 No Content. Кроме того, заголовок Allow должен индентифицировать методы GET и POST как разрешённые. Методы options, assert_no_entity и assert_allowed_methods берутся из RESTful Rails plugin.

Команда rake test:functionals должна выдать ошибку, поскольку в контроллере ещё нет ресурса :collection.

Первым делом, отключим ресурс :collection, чтобы функциональные тесты пока что перестали выдавать ошибки. А также следующее в app/controllers/book_controller.rb:

resource :collection do |r|
  r.post do
  end
end

Теперь команда rake test:functionals не выдаст ошибок.

Мы отключили пока только POST, однако, ничего не было сказано о GET. Ресурс RESTful Rails обрабатывает GET практически так же, как и обычный метод Rails: если вы не используете redirect и render, будет отображаться шаблон с тем же именем (если доступен).

Вспомогательная система

Пришел момент, когда нам потребуется тестовая информация, чтобы было с чем работать. Мы ещё раз воспользуемся вспомогательной системой Books, созданной нами для тестирования модели. Просто добавьте следующую строчку в метод setup в test/functional/book_controller_test.rb:

fixtures :books

Просмотр списка книг

Пусть даже запросы GET обрабатываются автоматически, нам все ещё необходимо посмотреть, что произойдёт, когда выполнится GET для :collection. Нам требуется, чтобы шаблон собрания книг загружался и отображался в виде списка всех книг базы данных в формате XML. Чтобы убедиться в этом, добавим в test/functional/book_controller_test.rb тест:

def test_get_collection
  get :collection
  assert_response HTTP::Status::OK
  assert_template 'collection'
  assert_equal 'application/xml', @response.content_type

  with_options :tag => 'books' do |test|
    test.assert_tag :children => { :count  => 1, :only => { :tag => 'title', :content => 'Books' } }
    test.assert_tag :children => { :count  => 1, :only => { :tag => 'book',  :content => ''      } }
  end

  with_options :tag => 'book' do |test|
    test.assert_tag :children => { :count  => 1, :only => { :tag => 'id',    :content => books(:http_book).id.to_s } }
    test.assert_tag :children => { :count  => 1, :only => { :tag => 'title', :content => books(:http_book).title   } }
    test.assert_tag :children => { :count  => 1, :only => { :tag => 'link',  :attributes => { :href => @controller.url_for(:action => 'by_id', :id => books(:http_book)) } } }
  end
end

Это нужно, чтобы убедиться в том, что по выполнении GET :collection будет возвращён код состояния 200 OK. Также шаблон collection должен использоваться для отображения результатов в определённом формате XML.

Команда rake test:functionals выдаст ошибку, поскольку мы ещё не создали шаблон XML.

До того, как создать шаблон, нам потребуется способ получить список всех книг из базы данных. Добавьте одну строчку в начало ресурса :collection в app/controllers/book_controller.rb:

resource :collection do |r|
  conditions << @books = Book.find(:all)

  r.post do
  end
end

Обратите внимание, что присваивание @book к conditions согласуется с REST на Rails. Это разрешит обработку условного запроса, который может быть в дальнейшем описан более детально.

Далее создайте шаблон app/views/book/collection.rxml следующего вида:

xml.instruct!

xml.books do
  xml.title 'Books'

  @books.each do |book|
    xml.book do
      xml.id    book.id
      xml.title book.title
      xml.link  :href => url_for(:only_path => false, :action => 'by_id', :id => book)
    end
  end
end

Команда rake test:functionals теперь не выдаст ошибок.

Пополнение списка книг

Итак, каким же образом нам следует обрабатывать POST в :collection? Ну, процесс состоит в том, чтобы добавить книгу в базу, а также перенаправить клиента по адресу новой книги. Учитывая это, добавим следующее в test/functional/book_controller_test.rb:

def test_post_collection
  new_book = { :title => 'test' }

  post :collection, :book => new_book
  assert_response HTTP::Status::CREATED

  id = Book.maximum('id')
  assert_location :action => 'by_id', :id => id

  book = Book.find(id)
  assert_kind_of Book, book
  assert_equal new_book[:title], book.title
  assert_equal new_book[:description], book.description
end

Это проверка на то, чтобы при выполнении POST для :collection, возвращался код состояния 201 Created. Кроме того, следует правильно установить заголовок Location, а также выполнена проверка базы данных, что новая книга была действительно внесена в базу.

Команда rake test:functionals выдаст ошибку, поскольку мы не добавили обработчик POST для :collection.

Для обработки запросов POST перепишем обработчик r.post в app/controllers/book_controller.rb:

r.post do
  @book = Book.new params[:book]
  if @book.save
    render_post_success :action => 'by_id', :id => @book
  end
end

В этом примере мы используем render_post_success метод из REST на Rails, который возвращает код 201 Created и помещает URI новой книги в заголовок Location.

Теперь команда rake test:functionals выполнится без ошибок.

Теперь мы закончили с ресурсом :collection. Он обрабатывает запросы GET, HEAD, OPTIONS и POST с помощью всего девяти строчек кода. Далее мы перейдём к ресурсу :by_id, который представляет собой книгу, используя её ID в базе данных.

Ресурс by_id

Ресурс :by_id представляет собой одну из книг, идентифицируемую по её ID в базе данных. Нам потребуется просматривать книгу с помощью метода GET, вносить изменения с помощью PUT, и удалять с помощью метода DELETE. Добавим в test/functional/book_controller_test.rb тест, который проверит возможность перечисленного:

def test_options_by_id
  options :by_id, :id => books(:http_book).id
  assert_response HTTP::Status::NO_CONTENT
  assert_no_entity
  assert_allowed_methods :get, :put, :delete
end

С помощью этого мы сможем убедиться, что по выполнении OPTIONS для :by_id, будет возвращён код состояния 204 No Content. А также заголовок Allow должен определять, что разрешены методы GET, PUT и DELETE.

Команда rake test:functionals должна выдать ошибку, поскольку для ресурса :by_id он ещё не создан.

Воспользуемся способом, очень похожим на тот, что мы применяли для ресурса :collection — мы извлечем ресурс :by_id, чтобы на данный момент тесты на функциональность выполнялись без ошибок. Добавим следующие строки в app/controllers/book_controller.rb:

resource :by_id do |r|
  r.put do
  end

  r.delete do
  end
end

И вновь, поскольку RESTful Rails plugin обрабатывает запросы так же, как и обычный Rails, нам не требуется ничего предпринимать для обработки GET.

Теперь команда rake test:functionals выполнится без ошибок.

Просмотр книг

Нам следует проверить, что произойдёт, когда выполнится GET для :by_id. В нашем случае нам потребуется, чтобы шаблон by_id загружался и отображал единственную книгу из базы данных в формате XML. Убедимся в этом, добавив следующее в test/functional/book_controller_test.rb:

def test_get_by_id
  get :by_id, :id => books(:http_book).id
  assert_response HTTP::Status::OK
  assert_template 'by_id'
  assert_equal 'application/xml', @response.content_type

  with_options :tag => 'book' do |test|
    test.assert_tag :children => { :count  => 1, :only => { :tag => 'id',          :content => books(:http_book).id.to_s     } }
    test.assert_tag :children => { :count  => 1, :only => { :tag => 'title',       :content => books(:http_book).title       } }
    test.assert_tag :children => { :count  => 1, :only => { :tag => 'description', :content => books(:http_book).description } }
  end
end

Это проверка на то, чтобы по выполнении GET для :by_id возвращался код состояния 200 OK, а также шаблон by_id использовался для отображения результатов в определённом формате XML.

Команда rake test:functionals должна выдать ошибку, поскольку мы ещё не создали шаблон XML.

До создания шаблона нам в первую очередь потребуется найти способ извлечь книгу из базы данных, используя ID из URI. Добавьте одну строчку в начало ресурса :by_id в app/controllers/book_controller.rb, чтобы он стал выглядеть так:

resource :by_id do |r|
  conditions << @book = Book.find(params[:id])

  r.put do
  end

  r.delete do
  end
end

Далее создайте шаблон app/views/book/by_id.rxml следующего вида:

xml.instruct!
@book.to_xml

Тест rake test:functionals пройдёт без ошибок.

Изменение книги

Теперь нам нужна возможность использовать PUT для изменения книги по её ID. Мы протестируем эту возможность, добавив следующее в test/functional/book_controller_test.rb:

def test_put_by_id
  changed_book = { :title => 'a different title', :description => 'a different description' }

  id = books(:http_book).id

  put :by_id, :id => id, :book => changed_book
  assert_response HTTP::Status::NO_CONTENT
  assert_no_entity

  book = Book.find id
  assert_kind_of Book, book
  assert_equal changed_book[:title], book.title
  assert_equal changed_book[:description], book.description
end

С помощью этого происходит проверка, что по выполнении PUT для :by_id будет возвращён код состояния 204 No Content. Тест проверит базу данных, чтобы убедиться, что запись успешно была изменена.

Команда rake test:functionals должна вернуть ошибку, поскольку мы ещё не добавили обработчик PUT для :by_id.

Для обработки запросов PUT обновим обработчик r.put в app/controllers/book_controller.rb с помощью следующих строк:

r.put do
  @book.attributes = params[:book]
  if @book.save
    render_put_success
  end
end

Воспользуемся методом render_put_success из RESTful Rails, который возвращает код состояния 204 No Content.

Теперь команда rake test:functionals должна выполниться без ошибок.

Удаление книги

И, наконец, нам потребуется DELETE для удаления книги по её ID.

Тест, который мы добавим в test/functional/book_controller_test.rb выглядит следующим образом:

def test_delete_by_id
  id = books(:http_book).id

  delete :by_id, :id => id
  assert_response HTTP::Status::NO_CONTENT
  assert_no_entity

  assert_raise(ActiveRecord::RecordNotFound) { Book.find id }
end

С помощью этого теста мы удостоверимся, что по выполнении DELETE для :by_id будет возвращён код состояния 204 No Content. Тест делает проверку базу данных, чтобы удостовериться, что запись была успешно удалена.

Команда rake test:functionals должна выдать ошибку, поскольку мы ещё не добавили обработчик DELETE в :by_id.

Для обработки запросов DELETE приведём обработчик r.delete в app/controllers/book_controller.rb к следующему виду:

r.delete do
  if @book.destroy
    render_delete_success :id => nil
  end
end

Это всего лишь вызовет @book.destroy и в случае успеха выполнит render_delete_success.

Теперь команда rake test:functionals не выдаст ошибки.

Доверяй, но проверяй

Всегда приятно видеть, как успешно работает программа в тестовых случаях, но что насчёт реального положения дел? Когда я пишу свои тесты, то люблю делать двойную проверку, чтобы убедиться, что всё идеально работает. Давайте напрямую выполним пару запросов, используя старый добрый curl.

Проверочный просмотр списка книг

Прежде чем приступить, нам следует поднять тестовый сервер с помощью следующей команды:

ruby script/server

Теперь откроем второй экземпляр командной строки и выполним следующее:

curl http://localhost:3000/books/

Ожидаемый отклик выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
<books>
  <title>Books</title>
</books>

Как можно видеть, в списке пока что нет ни одной книги.

Тестовый просмотр списка книг

Далее создадим одну книгу:

curl \
  -i \
  -X POST \
  -H 'Content-Type: application/xml' \
  -d '<book><title>a title</title><description>a description</description></book>' \
  http://localhost:3000/books/

Ответ на данный запрос будет включать несколько заголовков, но нам нужны только некоторые:

HTTP/1.1 201 Created
Location: http://localhost:3000/books/1

Обратите внимание на URI в заголовке Location, которым мы вот-вот воспользуемся.

Убедимся, что новая книга наличествует в собрании:

curl http://localhost:3000/books/

Ожидаемый ответ выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
<books>
  <title>Books</title>
  <book>
    <id>1</id>
    <title>a title</title>
    <link href="http://localhost:3000/books/1"/>
  </book>
</books>

Убедитесь, что ссылка в href соответствует указанной в заголовке Location, полученном нами на предыдущем шаге.

Тестовый просмотр книги

Последуем заголовку Location из предыдущего шага:

curl http://localhost:3000/books/1

Ожидаемый ответ выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
<book>
  <title>a title</title>
  <id type="integer">1</id>
  <description>a description</description>
</book>

Тестовое изменение книги

Обновите книгу, используя PUT:

curl \
  -i \
  -X PUT \
  -H 'Content-Type: application/xml' \
  -d '<book><title>a new title</title><description>a new description</description></book>' \
  http://localhost:3000/books/1

Это также возвратит несколько заголовков, но на данном этапе нам потребуется лишь первая строчка:

HTTP/1.1 204 No Content

Вновь возьмём книгу, чтобы просмотреть изменения:

curl http://localhost:3000/books/1

Ожидаемый ответ выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
<book>
  <title>a new title</title>
  <id type="integer">1</id>
  <description>a new description</description>
</book>

Тестовое удаление книги

Мы удалим книгу следующим способом:

curl -i -X DELETE http://localhost:3000/books/1

И вновь мы получим несколько заголовков, но тот, из которого мы узнаем об успешном выполнении DELETE, расположен в первой строчке:

HTTP/1.1 204 No Content

Чтобы убедиться, что книга удалена, выполним запрос GET:

curl http://localhost:3000/books/

Ожидаемый ответ выглядит так:

<?xml version="1.0" encoding="UTF-8"?>
<books>
  <title>Books</title>
</books>

Теперь собрание не содержит книг, как и ожидалось.

Только начало

Итак, теперь у нас есть простое приложение на RESTful Rails, которое было полностью протестировано, а также координация методов HTTP. Мы пользовались HTTP-методом OPTIONS, чтобы определить методы, поддерживаемые всеми ресурсами, и мы основывали наши тесты на относительно простом протоколе из REST.

Поскольку мы строили приложения на RESTful Rails с использованием Ruby on Rails, то мы находимся лишь в начале пути к огромным возможностям. В данное время интерес к HTTP и архитектуре REST постоянно растёт со стороны команды разработчиков ядра Rails, а, в частности, со стороны Дэвида Хейнемейера Хэнссона. Проект RESTful Rails хорошо подготовлен к старту за счёт координации методов; а на будующее запланированы: условный GET, HTTP-идентификация и многое другое.

Учитывая мощное развитие Ruby on Rails, можно без оглядки утверждать, что в ближайшие месяцы вы увидие больше приложений на REST, а сообщество улучшит свое понимание протокола HTTP.



XML.com Copyright © 1998-2007 O'Reilly Media, Inc.
Перевод: xmlhack.ru Copyright © 2000-2007 xmlhack.ru