Pull to refresh

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

Данная статья — перевод оригинального анонса 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 http://localhost:3000/users/1
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.