(Rails) PATCH — новый базовый HTTP-метод для обновлений

29 Фев
2012

Данная статья — перевод оригинального анонса Edge Rails: PATCH is the new primary HTTP method for updates.

Что такое PATCH?

HTTP-метод PUT предназначен для создания или замены ресурса по заданному URL. Возьмем, к примеру, файл. Когда вы загружаете файл в S3 по определенному URL, вы либо хотите создать его по тому адресу, либо заменить уже имеющийся там файл. Это PUT-запрос.

Далее представим веб-приложение, имеющее модель Invoice (счет), которая содержит флаг paid (оплачен?). Как установить значение этого флага в стиле RESTful? Установка paid=1 через PUT-запрос по адресу /invoices/:id не подойдет, т.к. такой запрос не обеспечит полной пересылки состояния счета.

С учетом ограничений методов GET, POST, PUT и DELETE, традиционным советом будет определить флаг оплаты в качестве отдельного ресурса. Тем самым вы определяете маршрут для установки paid=1 через PUT-запрос к /invoices/:id/paid. Вам придется поступить подобным образом, т.к. PUT не позволяет произвести лишь частичное обновление ресурса.

Давайте подумаем о самых обычных формах на обновление в типичном Rails-приложении. Как часто вы посылаете полное представление ресурса? Не всегда, быть может даже довольно редко в вашей практике. К примеру, временные метки created_at и updated_at обычно не управляются конечным пользователем, хотя зачастую они считаются принадлежащими ресурсу, который мапится на запись БД.
Ещё стоит учитывать, что PUT — идемпотентный метод. Вы должны быть готовы принять такой запрос сколь угодно много раз и каждый раз возвратить корректный ресурс. Такое нарушение привычной идиомы иногда случается, когда посредством вложенных атрибутов создаются дочерние ресурсы, приводящие к параллельному обновлению родительского.

Хотя теоретически ничто не препятствует применению PUT для пересылки частичных обновлений, но фактически семантика замены уже была учтена во время стандартизации HTTP. Метод PATCH был представлен в 1995 году, а позднее вошел в стандарты. PATCH — это метод, который не объявляется ни безопасным, ни идемпотентным, и позволяет производить полное или частичное обновление, возможно с побочным эффектом на смежные ресурсы.

На практике, как вы можете видеть, PATCH обычно в большей степени подходит для обновления ресурсов, чем PUT. В Ruby on Rails он естественным образом соотносится с методом update_attributes, который используется для обновления записей.

Тем самым, PATCH в Rails 4.0 выдвигается на первые роли.

Маршрутизация

Несмотря на серьезность изменений, мы планируем реализовать их так, чтобы сохранить обратную совместимость. Когда ресурс объявляется в routes.rb, например:

resource :users


экшен на обновление в контроллере UsersController в Rails 4.0 будет по-прежнему называться update.

Запрос PUT по адресу /users/:id в Rails 4.0 будет, как и сегодня, маршрутизироваться к методу update. Т.о. если у вас есть API, которое производит вызовы PUT, оно по-прежнему будет работать.

Однако маршрутизация в Rails 4.0 также будет направлять на экшен update и PATCH-запросы к /users/:id. Т.е. и PUT и PATCH в Rails 4.0 будут маршрутизироваться к update.

Формы

Форма к сохраняемому ресурсу:

form_for @user


получит «patch» в скрытом поле «_method». Позволю себе заметить, что хак с «_method» — это просто способ обойти существующие ограничения браузеров. Как вы, вероятно, знаете, Rails вынуждена оперировать реальными методами HTTP, в т.ч. для обеспечения запросов PUT, DELETE, а теперь и PATCH.

Практическое применение

Запросы PATCH доступны во всех местах, где в текущий момент применимы остальные HTTP-методы. DSL маршрутизации подвергнется расширению, в частности хэш :via теперь будет понимать символ :patch. Тесты также смогут обрабатывать PATCH-запросы. Подробности см. в оригинальном коммите.

Будет ли моё приложение понимать PATCH?

Да. Я лично проверил Apache, nginx, Phusion Passenger, Unicorn, Thin и WEBrick: они все понимают запросы PATCH. HTTP-клиенты также должны в целом справляться с PATCH-запросами. Вы можете попробовать выполнить в curl такой запрос:

curl -d'user[name]=wadus' -X PATCH localhost:3000/users/1
По материалам Хабрахабр.



загрузка...

Комментарии:

Наверх