Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Experimenting with an implementation for before-save and after-load c…

…allbacks.
  • Loading branch information...
commit 8268e0e6c6953389049132914c4be7831e4c5001 1 parent a92e572
Constantine Vetoshev authored
41 src/appengine_magic/services/datastore.clj
View
@@ -15,6 +15,14 @@
;;; ----------------------------------------------------------------------------
+;;; forward declarations
+;;; ----------------------------------------------------------------------------
+
+(declare run-after-load)
+
+
+
+;;; ----------------------------------------------------------------------------
;;; helper variables and constants
;;; ----------------------------------------------------------------------------
@@ -124,6 +132,8 @@
group parent.")
(get-entity-object [this]
"Returns a datastore Entity object instance for the record.")
+ (run-after-load [this]
+ "Invokes the after-load callback.")
(save! [this]
"Writes the given entity to the data store."))
@@ -198,8 +208,9 @@
"entity has no valid :key metadata, and has no fields marked :key")))))
-(defn get-entity-object-helper [entity-record kind]
- (let [key-object (get-key-object entity-record)
+(defn get-entity-object-helper [entity-record kind before-save]
+ (let [entity-record (before-save entity-record)
+ key-object (get-key-object entity-record)
clj-properties (get-clj-properties entity-record)
entity-meta (meta entity-record)
entity (cond key-object (Entity. key-object)
@@ -341,16 +352,17 @@
model-record (record entity-record-type)]
(map #(let [v (.getValue %)]
(with-meta
- (merge model-record
- (entity->properties (.getProperties v)
- (get-clj-properties model-record)))
+ (run-after-load
+ (merge model-record
+ (entity->properties (.getProperties v)
+ (get-clj-properties model-record))))
{:key (.getKey v)}))
entities))
;; handles singleton values
(let [key-object (make-key-from-value key-value-or-values parent)
entity (.get (get-datastore-service) key-object)
raw-properties (into {} (.getProperties entity))
- entity-record (record entity-record-type)]
+ entity-record (run-after-load (record entity-record-type))]
(with-meta
(merge entity-record (entity->properties raw-properties
(get-clj-properties entity-record)))
@@ -378,8 +390,10 @@
(defmacro defentity [name properties &
- {:keys [kind]
- :or {kind (unqualified-name name)}}]
+ {:keys [kind before-save after-load]
+ :or {kind (unqualified-name name)
+ before-save identity
+ after-load identity}}]
;; TODO: Clojure 1.3: Remove the ugly Clojure version check.
(let [clj13? (fn [] (and (= 1 (:major *clojure-version*))
(= 3 (:minor *clojure-version*))))
@@ -407,7 +421,9 @@
(get-key-object [this# parent#]
(get-key-object-helper this# ~key-property ~kind parent#))
(get-entity-object [this#]
- (get-entity-object-helper this# ~kind))
+ (get-entity-object-helper this# ~kind ~before-save))
+ (run-after-load [this#]
+ (~after-load this#))
(save! [this#]
(save!-helper this#)))))
@@ -494,9 +510,10 @@
;; unknown type; just use a basic EntityProtocol
(EntityBase.))]
(map #(with-meta
- (merge model-record
- (entity->properties (.getProperties %)
- (get-clj-properties model-record)))
+ (run-after-load
+ (merge model-record
+ (entity->properties (.getProperties %)
+ (get-clj-properties model-record))))
{:key (.getKey %)})
results)))))
22 test/test/appengine_magic/services/datastore.clj
View
@@ -15,6 +15,14 @@
(ds/defentity Parent [name child-counter])
(ds/defentity Child [name parent])
+(ds/defentity O1 [x]
+ :before-save (fn [entity] (assoc entity :x (inc (:x entity)))))
+(ds/defentity O2 [x]
+ :after-load (fn [entity] (assoc entity :x (dec (:x entity)))))
+(ds/defentity O3 [x y]
+ :before-save #(assoc % :x (str "modified before save " x))
+ :after-load #(assoc % :y (str "modified after load " y)))
+
(deftest basics
(let [alice (Author. "Alice")
@@ -128,3 +136,17 @@
(dotimes [i max]
(make-author i))
(is (= max (ds/query :kind Author :count-only? true)))))
+
+
+(deftest lifecycle-callbacks
+ (let [o1 (ds/save! (O1. 1))]
+ (is (= 2 (:x (first (ds/query :kind O1))))))
+ (let [o2 (ds/save! (O2. 1))]
+ (is (= 0 (:x (first (ds/query :kind O2))))))
+ (let [o3 (O3. 10 20)]
+ (is (= 10 (:x o3)))
+ (is (= 20 (:y o3)))
+ (ds/save! o3)
+ (let [o3 (first (ds/query :kind O3))]
+ (is (= "modified before save 10" (:x o3)))
+ (is (= "modified after load 20" (:y o3))))))
Please sign in to comment.
Something went wrong with that request. Please try again.