Как смоделировать действие в REST?

#ruby-on-rails #rest

#ruby-on-rails #rest

Вопрос:

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

Я хотел бы, чтобы Task поддерживал запуск / остановку задачи. При запуске будет создан новый временной интервал с текущим временем. Stop добавит end_time к последнему временному интервалу.

Я думал, что URL-адрес REST будет таким: PUT /tasks/1011?do=start PUT /tasks/1011?do=stop

или, может быть, ПОМЕСТИТЬ /tasks/1011/start ПОМЕСТИТЬ /tasks/1011/stop

Как правильно создать этот стиль REST?

Ответ №1:

Я думаю, что Пол действительно близок к этому, но важно отметить, что чистый REST требует объекта / существительного в качестве ресурса. Учитывая, что я не сторонник REST purest, я просто добавляю свои 0.02 доллара, поскольку это относится непосредственно к REST. Это, вероятно, более технически правильно:

 Request: 
  POST /tasks/1011/timeperiod
Response: 201 Created response status with a Location header that points to 
  GET /tasks/1011/timeperiod/(identifier)
  

Затем вы должны иметь возможность использовать / tasks/ 1011/timeperiod / (идентификатор) для обновления этого. Остановка времени, вероятно, потребовала бы ввода, сброс (или, скорее, удаление) времени потребовал бы УДАЛЕНИЯ. Ваша страница состояния должна появляться всякий раз, когда они фактически попадают на GET /tasks /1011/timeperiod/ (идентификатор).

Подумайте о парах ключ-значение объекта / идентификатор. Параметры в GET не должны быть обязательными.

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

1. Согласованные ресурсы должны быть object / nouns. Один из способов, которым я справлялся с этим, заключается в том, что ресурс является контроллером для действия, что является компромиссом на первый взгляд, многие действия, которые мы хотим выполнить, не вписываются в методы, определенные HTTP. Это всего лишь изменение имени, которое у вас затем есть /tasks/1011/start_controller . Можно также привести аргумент для главного контроллера, где действие для предварительной обработки находится в теле запроса POST /task/1011/controller action=start , но я бы исследовал компромиссы, связанные с этим.

2. Что касается меня (лично), я мог бы сделать это любым из предложенных способов. Я просто пытаюсь добраться до сути REST и проблемы с шаблоном URI, о которой спрашивал mbdev. Я стараюсь думать о REST не столько как о наборе законов, сколько как о наборе стратегий и применять их к проблемам, используя здравый смысл.

3. Использование этой стратегии является правильным, когда дело доходит до REST, однако ее сложно реализовать на стороне клиента. Поскольку для остановки задачи потребуется поместить текущую дату с помощью PUT с помощью javascript. В то время как действие может обработать это на стороне сервера, что проще.

Ответ №2:

Вот одна из альтернатив. Извлеките задачу следующим образом,

 GET /task/1011
  

Затем, чтобы запустить задачу, ОПУБЛИКУЙТЕ ее следующим образом,

 POST /ActiveTasks  
  

и завершить задачу,

 POST /InactiveTasks   
  

На самом деле не имеет значения, как выглядят URI, если вы используете следующее представление для ресурса задачи:

 <Task>
  <Description>Do some stuff</Description>
  <Status>Active</Status>
  <Link rel="end" Method="POST" href="/InactiveTasks"/>
</Task>
  

или

 <Task>
  <Description>Do some stuff</Description>
  <Status>InActive</Status>
  <Link rel="start" Method="POST" href="/ActiveTasks"/>
</Task>
  

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

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

1. Я предпочитаю этот метод, если не вижу более простого. Это решение будет применимо и к другим сценариям. Например, сейчас у меня есть проект, в котором я должен «подтвердить» операцию обновления элемента. Мы будем реализовывать его, отправляя вместе с элементом URL подтверждения для ВКЛЮЧЕНИЯ.

Ответ №3:

Вы хотите максимально соответствовать определениям HTTP-методов при использовании REST, чтобы воспользоваться преимуществами унифицированного интерфейса. Используя это правило, вы бы не захотели использовать PUT или строку запроса для передачи действия. PUT не подошел бы, потому что он должен использоваться для замены ресурса.

POST — это метод, который вы хотели бы использовать. POST /tasks/1011/start предпочтительно с кодом ответа 303, чтобы перенаправлять их на страницу состояния (если это необходимо для ваших вариантов использования) или с кодом 400, если запуск не удался. Аналогично для остановки задачи.

Я настоятельно рекомендую RESTful Web Services Cookbook, поскольку я использую его в качестве руководства к этому ответу, и он охватывает другие распространенные вопросы REST.

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

1. POST используется для создания ресурса, и в этом случае Задача уже существует. Поэтому, возможно, было бы лучше указать изменение статуса на начато / остановлено

2. Исправьте, этот POST обычно используется для создания ресурса, в котором вы хотите, чтобы сервер определял, где должен располагаться этот новый ресурс, но его определение достаточно широкое, чтобы его можно было использовать для других целей. PUT имеет концепцию идемпотентности, которая сводится к многократному запросу одного и того же ресурса, который должен иметь одинаковый эффект, что в данном случае звучит не так, как вы хотите. POST, с другой стороны, не является идемпотентным.