diff --git a/src/toucan2/instance.clj b/src/toucan2/instance.clj index d2d9bb1..748db40 100644 --- a/src/toucan2/instance.clj +++ b/src/toucan2/instance.clj @@ -41,7 +41,7 @@ ```clj (instance-of? ::bird (instance ::toucan {})) ; -> true - (instance-of? ::toucan (instance ::bird {})) ; -> false + (instance-of? ::toucan (instance ::bird {})) ; -> false ```" [model x] (and (instance? x) diff --git a/src/toucan2/protocols.clj b/src/toucan2/protocols.clj index e7c9f21..967181d 100644 --- a/src/toucan2/protocols.clj +++ b/src/toucan2/protocols.clj @@ -45,8 +45,8 @@ "Get a map with any changes made to `instance` since it came out of the DB. Only includes keys that have been added or given different values; keys that were removed are not counted. Returns `nil` if there are no changes.")) -;;; `nil` and `IPersistentMap` can implement so of the methods that make sense for them -- `nil` or a plain map doesn't -;;; have any changes, so [[changes]] can return `nil`. I don't know what sort of implementation for stuff like +;;; `nil` and `IPersistentMap` can implement the methods that make sense for them: `nil` or a plain map doesn't have any +;;; changes, so [[changes]] can return `nil`. I don't know what sort of implementation for stuff like ;;; [[with-original]] or [[with-current]] makes sense so I'm not implementing those for now. (extend-protocol IRecordChanges nil @@ -76,6 +76,7 @@ this) (with-current [_this new-current] new-current) + ;; treat the entire map as `changes` -- that way if you accidentally do something like ;; ;; (merge plain-map instance) diff --git a/test/toucan2/tools/after_update_test.clj b/test/toucan2/tools/after_update_test.clj index d9faf59..ce7252b 100644 --- a/test/toucan2/tools/after_update_test.clj +++ b/test/toucan2/tools/after_update_test.clj @@ -3,7 +3,9 @@ [clojure.string :as str] [clojure.test :refer :all] [clojure.walk :as walk] + [toucan2.insert :as insert] [toucan2.instance :as instance] + [toucan2.protocols :as protocols] [toucan2.select :as select] [toucan2.test :as test] [toucan2.test.track-realized-columns :as test.track-realized] @@ -175,3 +177,28 @@ (generated-name `(after-update/define-after-update :model-2 [~'venue] ~'venue))))))) + +(derive ::people.bird-lovers ::test/people) + +;; Unfortunately the changes-available-test needs to do something side-effecty since the value of after-update is +;; discarded. Toggling an atom seemed like the easiest side effect. +(def ^:private bird-lover-found? (atom false)) + +(after-update/define-after-update ::people.bird-lovers + [person] + (when ((fnil str/includes? "") (:name (protocols/changes person)) "Cam") + (reset! bird-lover-found? true)) + person) + +(deftest ^:synchronized changes-available-test + (test/with-discarded-table-changes :people + (testing "Changes made via update should be available in after-update" + (reset! bird-lover-found? false) + (let [[{row-id :id}] (insert/insert-returning-instances! ::people.bird-lovers + {:name "Gwynydd Purves Wynne-Aubrey Meredith"})] + ;; Update without the relevant changes: + (update/update! ::people.bird-lovers row-id {:created-at (LocalDateTime/parse "2017-01-01T00:00")}) + (is (false? @bird-lover-found?)) + ;; Update with relevant changes: + (update/update! ::people.bird-lovers row-id {:name "Cam Era"}) + (is (true? @bird-lover-found?))))))