Blog::Entities::Article ::Repository.new
@@database
end
Этот подход позволит добавить перегрузку #repository
для каждого класса сущности, если в будущем будут добавлены другие. Опять же, мы могли бы, конечно, реализовать что-то более изысканным и надежным способом, но, учитывая, что у нас будет только одна сущность, использование перегрузок при кэшировании репозитория в переменной класса будет достаточно хорошим. Как говорится,
Теперь, когда у нас есть возможность получать все статьи, а также отдельные статьи по идентификатору, мы можем перейти к созданию конечных точек, добавив в контроллер статей следующие методы:
@[ARTA::Get("/article/{id}")]
def article(id : Int64) : Blog::Entities::Article
article = @entity_manager.repository(Blog::Entities::Article)
.find? Id
if article.nil?
raise ATH::Exceptions::NotFound.new "An item with the provided ID could not be found."
end
article
end
@[ARTA::Get("/article")]
def articles : Array(Blog::Entities::Article)
@entity_manager.repository(Blog::Entities::Article).find_all end
Первая конечная точка вызывает #find?
метод для возврата статьи с предоставленным идентификатором. Если он не существует, он возвращает более полезный ответ об ошибке 404
. Следующая конечная точка возвращает массив всех сохраненных статей.
Как и раньше, когда мы начали с конечной точки #create_article
и узнали об ATH::RequestBodyConverter
, существует лучший способ обработки чтения конкретной статьи из базы данных. Мы можем определить наш собственный преобразователь параметров, который будет использовать параметр пути идентификатора, извлекать его из базы данных и передавать в действие, при этом он будет достаточно универсальным, чтобы его можно было использовать для других имеющихся у нас объектов. Создайте
@[ADI::Register]
class Blog::Converters::Database < ATH::ParamConverter
def initialize(@entity_manager : Blog::Services
::EntityManager);
end
# :inherit:
def apply(request : ATH::Request, configuration :
Configuration(T)) : Nil forall T
id = request.attributes.get "id", Int64
unless model = @entity_manager.repository(T).find? Id
raise ATH::Exceptions::NotFound.new "An item with the provided ID could not be found."
end
request.attributes.set configuration.name, model, T
end
end
Как и в случае с предыдущим прослушивателем, нам нужно сделать прослушиватель сервисом с помощью аннотации ADI::Register
. Фактическая логика включает в себя извлечение параметра пути идентификатора из атрибутов запроса, использование его для поиска связанного объекта, если таковой имеется, и установку объекта в атрибутах запроса.
Если объект с предоставленным идентификатором не найден, мы возвращаем ответ об ошибке 404
.
Последняя ключевая часть того, как это работает, относится к ранее в главе, когда мы изучали, как Athena предоставляет аргументы для каждого действия контроллера. Одним из таких способов разрешения аргументов является использование атрибутов запроса, которые можно рассматривать как хранилище ключей/значений для произвольных данных, связанных с запросом, к которым автоматически добавляются параметры пути и запроса.
В контексте нашего конвертера метод article
, для разрешенного объекта. Затем Athena увидит, что это действие контроллера имеет параметр с именем article
, проверит, существует ли атрибут с таким именем, и предоставит его действию, если он существует. Используя этот конвертер, мы можем обновить действие #article
следующим образом:
@[ARTA::Get("/article/{id}")]
@[ATHA::ParamConverter("article", converter: