Презентер

Презентер возвращает view model, которая передается в шаблон. View model содержит все данные, всю логику, так, чтобы шаблон был максимально простым и не требовал модульного тестирования. Все ссылки, активность кнопок устанавливаются тут. Таким образом при необходимости легко написать модульный тест для презентера.

(ns publicator.web.presenters.layout
  (:require
   [publicator.use-cases.services.user-session :as user-session]
   [publicator.web.routing :as routing]
   [ring.middleware.anti-forgery :as anti-forgery]))

(defn present [req]
  (cond-> {:csrf anti-forgery/*anti-forgery-token*}
    (user-session/logged-in?)
    (assoc :log-out {:text   "Log out"
                     :url    (routing/path-for :user.log-out/process)})

    (user-session/logged-out?)
    (assoc :register {:text "Register"
                      :url  (routing/path-for :user.register/initial-params)})

    (user-session/logged-out?)
    (assoc :log-in {:text "Log in"
                    :url  (routing/path-for :user.log-in/initial-params)})))
(ns publicator.web.presenters.post.list
  (:require
   [publicator.use-cases.interactors.post.list :as interactor]
   [publicator.use-cases.interactors.post.create :as interactors.post.create]
   [publicator.use-cases.interactors.post.update :as interactors.post.update]
   [publicator.domain.aggregates.user :as user]
   [publicator.web.routing :as routing]))

(defn- post->model [post authorization]
  {:id             (:id post)
   :url            (routing/path-for :post.show/process {:id (-> post :id str)})
   :update-url     (routing/path-for :post.update/initial-params {:id (-> post :id str)})
   :title          (:title post)
   :can-update?    (= [::interactors.post.update/authorized] authorization)
   :user-full-name (::user/full-name post)})

(defn processed [posts]
  (let [authorizations (interactors.post.update/authorize (map :id posts))
        view-models    (map post->model posts authorizations)
        can-create?    (= [::interactors.post.create/authorized]
                          (interactors.post.create/authorize))]
    (cond-> {}
      :always     (assoc :posts view-models)
      can-create? (assoc :new {:text "New"
                               :url  (routing/path-for :post.create/initial-params)}))))