Blog::Converters::Database)]
def article(article : Blog::Entities::Article) :
Blog::Entities::Article
article
end
Та-да! Простой способ предоставления объектов базы данных непосредственно в качестве аргументов действия через их идентификаторы. Хотя на данный момент у нас уже довольно много конечных точек, связанных со статьями, нам все еще не хватает способа обновить или удалить статью. Давайте сначала сосредоточимся на том, как обновить статью.
Обновление статьи
На первый взгляд обновление записей базы данных может показаться простым, но на самом деле оно может быть довольно сложным из-за характера процесса. Например, чтобы обновить сущность, сначала необходимо получить ее текущий экземпляр, а затем применить к нему изменения. Изменения обычно представляются в виде тела запроса к конечной точке PUT
POST
. Проблема заключается в том, как применить изменения из нового тела запроса к существующей сущности.Сериализатор Athena имеет концепцию конструкторов объектов, которые управляют тем, как сначала инициализируется десериализуемый объект. По умолчанию они создаются обычным способом с помощью метода .new
Однако, поскольку это немного усложняет работу сериализатора Athena, а в нашей статье есть только два свойства, мы не собираемся это реализовывать. Если вам интересно, как это будет выглядеть, или вы хотите попробовать реализовать это самостоятельно, ознакомьтесь с рецептом кулинарной книги: https://athenaframework.org/cookbook/object_constructors/#db
. Он использует Granite ORM, но переключить его на наш EntityManager должно быть довольно просто.Вместо использования конструктора объекта мы просто собираемся вручную сопоставить значения из тела запроса и применить их к объекту, полученному из базы данных. Прежде чем мы сможем это сделать, нам сначала нужно обновить менеджер сущностей для обработки обновлений. Первым шагом является обновление #persist
def persist(entity : DB::Serializable) : Nil
entity.before_save if entity.responds_to? :before_save
if entity.id?.nil?
entity.after_save self.save entity
else
self.update entity
end
Где метод #update
private def update(entity : Blog::Entities::Article) : Nil
@@connection.exec(
%(UPDATE "articles" SET "title" = $1, "body" = $2,
"updated_at" = $3, "deleted_at" = $4 WHERE "id" = $5;),
entity.title,
entity.body,
entity.updated_at,
entity.deleted_at,
entity.id
)
end
Отсюда мы можем обновить нашу конечную точку #update_article
@[ARTA::Put("/article/{id}")] @[ATHA::ParamConverter("article_entity", converter:
Blog::Converters::Database)]
@[ATHA::ParamConverter("article", converter:
ATH::RequestBodyConverter)]
def update_article(article_entity : Blog::Entities::Article,
article : Blog::Entities::Article) : Blog::Entities::Article
article_entity.title = article.title
article_entity.body = article.body
@entity_manager.persist article_entity
article_entity
end
В этом примере мы используем два преобразователя параметров. Первый извлекает реальную сущность статьи из базы данных, а второй создает ее на основе тела запроса. Затем мы применяем статью тела запроса к сущности статьи и передаем ее в #persist
curl --request PUT 'http://localhost:3000/article/1'
--data-raw '{
"title": "New Title",