"body": "New Body",
"updated_at": "2022-04-09T05:13:30Z",
"created_at": "2022-04-09T04:47:09Z"
}'
Это приведет к такому ответу:
{
"id": 1, "title": "New Title",
"body": "New Body",
"updated_at": "2022-04-09T05:22:44Z",
"created_at": "2022-04-09T04:47:09Z"
}
Прекрасно! title
, body
, и updated_at
были обновлены, как и ожидалось, тогда как временные метки id
и create_at
из базы данных не были изменены.
И последнее, но не менее важное: нам нужна возможность удалить статью.
Мы можем обрабатывать удаления, еще раз обновив наш менеджер сущностей, включив в него метод #remove
, а также метод #on_remove
для наших сущностей, который будет обрабатывать настройку свойства delete_at
. Затем мы могли бы использовать преобразователь параметров базы данных на конечной точке DELETE
и просто предоставить #remove
разрешенному объекту.
Начните с добавления этого в менеджер сущностей:
def remove(entity : DB::Serializable) : Nil
entity.on_remove if entity.responds_to? :on_remove
self.update entity
end
А это к нашей статье:
protected def on_remove : Nil
@deleted_at = Time.utc
end
Наконец, действие контроллера будет выглядеть так:
@[ARTA::Delete("/article/{id}")]
@[ATHA::ParamConverter("article", converter:
Blog::Converters::Database)]
def delete_article(article : Blog::Entities::Article) : Nil
@entity_manager.remove article
end
Затем мы могли бы сделать запрос, например, curl --request DELETE 'http:// localhost:3000/article/1'
и увидеть в базе данных, что столбец delete_at
установлен. Потому что метод #find?
также отфильтровывает удаленные элементы, поэтому попытка удалить ту же статью еще раз приведет к ошибке 404
.
В некоторых случаях API может потребоваться поддержка возврата не только JSON. Athena предоставляет несколько способов улучшить согласование контента, обрабатывая несколько форматов ответов с помощью единственного возвращаемого значения из действия контроллера. Давайте взглянем.
На данный момент наш блог действительно собирается вместе. Мы можем создавать, получать, обновлять и удалять статьи. У нас также есть несколько довольно надежных абстракций, которые помогут будущему росту. Как упоминалось ранее в этой главе, если действия контроллера напрямую возвращают объект, это может помочь в обработке нескольких форматов ответов. Например, предположим, что мы хотели расширить наше приложение, разрешив ему возвращать статью как в формате HTML, так и в формате JSON, в зависимости от заголовка
Чтобы справиться с генерацией HTML, мы могли бы использовать встроенную функцию Crystal (ECR), которая по сути похожа на шаблонизацию во время компиляции. Однако было бы полезно иметь что-то более гибкое, похожее на PHP Twig, Python Jinja или Embedded Ruby (ERB). На самом деле существует кристальный порт Джинджи под названием Crinja, который мы можем использовать. Итак, сначала добавьте следующее в качестве зависимости к вашему shards install
и потребовав ее в
crinja:
github: straight-shoota/crinja
version: ~> 0.8.0
В Crinja есть модуль Crinja::Object
, который можно включить, чтобы обеспечить доступ к определенным свойствам/методам этого типа в шаблоне. Он также имеет подмодуль Auto
, который работает во многом аналогично JSON::Serializable
. Поскольку это модуль, он также позволит нам проверить, доступен ли конкретный объект для визуализации, чтобы мы могли обработать случай ошибки при попытке отобразить объект, который невозможно отобразить.
План установки такой:
1. Настройте согласование содержимого, чтобы конечная точка GET /article/{id}
отображалась как в формате JSON, так и в формате HTML.
2. Включите и настройте Crinja::Object::Auto
в нашей сущности статьи.
3. Создайте HTML-шаблон, который будет использовать данные статьи.
4. Определите собственный модуль визуализации для HTML, чтобы связать все воедино.