slagyr / gaeshi

Google App Engine library for Clojure
MIT License
39 stars 4 forks source link

Datastore Usage Example #7

Closed philipbjorge closed 12 years ago

philipbjorge commented 12 years ago

Hi Micah, First off I wanted to say thanks for writing gaeshi - it's proven to be much easier and clearer to get started with than appengine magic.

Can you provide an example of creating a record and storing it in the datastore? It'd also be nice to see an update to an existing record.

If there is already an open source project using this part of gaeshi, pointing me in that direction would be fine as well.

Thanks

LupusDei commented 12 years ago

First you need to use gaeshi.datastore. Then you do the following:

(defentity Example [test-field1] [test-field2 :default []] [created-at])

(defn create-example [] (save (example :test-field1 "some value" :test-field2 ["some" "vector"])))

(defn update-an-example [example] (save (assoc example :test-field1 "some new value")))

Saving is pretty straight forward. You can easily save anything you have defined as an entity. To create a new instance of that entity you just use its name '(example)' this generates an empty instance of the entity defined as Example. Your entities have a 'kind' field automatically added to them which allows gaeshi to figure out which sort of entity you are trying to save/update. It also means you can find all the entities of a kind:

(defn find-all-examples [] (find-by-kind "example"))

You can provide default values for when a field is not specifically assigned.

There are a few special fields like 'created-at' and 'updated-at' which are automatically set when the entity is saved.

To managed relationships between entities you should use their keys. for exp:

(defentity ExampleOwner [owner-name] [created-at] [updated-at] [example-key])

(defn create-owner-with-example [example] (save (example-owner :owner-name "Justin" :example-key (:key example))))

This was you can always do a lookup on the example-owner's example by doing:

(defn get-example-of-owner [example-owner] (find-by-key (:example-key example-owner)))

Gaeshi treats fields that end with 'key' or 'keys' as references to other entities. It saves those fields as 'key' types, and thus allows you to perform datastore lookups with them.

I hope this helps!

philipbjorge commented 12 years ago

Justin - I really appreciate the thorough explanation. It's helped immensely. One last question (for now :D) - How do I save a user to the database? The following code is not working for me.

(ns infinite-social-wall-he.model.user
  (:use [gaeshi.users :only (current-user current-user-logged-in?)])
  (:require [gaeshi.datastore :as ds]))

(ds/defentity MyUser
  [self]
  [page-name :default ""]
  [service-keys :default []])

(defn create-if-new-user []
  (when (current-user-logged-in?)
      (ds/save (my-user :self (current-user)))))

When I replace (current-user) with a string, it saves fine to the database, which I'm verifying by using count-by-kind. The reason I ask is because it looks like datastore supports this functionality based on datastore/types.clj Assuming I can store current-user, I assume I'd be able to filter on this property as well?

Would I be better off storing user attributes in some other way?

Thanks

slagyr commented 12 years ago

Philip,

(current-user) returns a map (which represents a com.google.appengine.api.users.User instance). It's probably best to persist the user as a User object rather than a map. To do that simply add the User type to your self field.

(require 'gaeshi.datastore.types)

(defentity MyUser [self :type com.google.appengine.api.users.User] …)

When saved, the self field will get packed into a User object. when loaded it will get unpacked into a map.

Micah

On Aug 30, 2012, at 1:05 AM, Philip Bjorge notifications@github.com wrote:

Justin - I really appreciate the thorough explanation. It's helped immensely. One last question (for now :D) - How do I save a user to the database? The following code is not working for me.

(ns infinite-social-wall-he.model.user (:use [gaeshi.users :only (current-user current-user-logged-in?)]) (:require [gaeshi.datastore :as ds]))

(ds/defentity MyUser [self] [page-name :default ""] [service-keys :default []])

(defn create-if-new-user [](when %28current-user-logged-in?%29 %28ds/save %28my-user :self %28current-user%29%29%29)) When I replace (current-user) with a string, it saves fine to the database, which I'm verifying by using count-by-kind. The reason I ask is because it looks like datastore supports this functionality based on datastore/types.clj Assuming I can store current-user, I assume I'd be able to filter on this property as well?

Would I be better off storing user attributes in some other way?

Thanks

— Reply to this email directly or view it on GitHub.

argestes commented 12 years ago

This example returns No implementation of method: :render of protocol: #'compojure.response/Renderable found for class: jack.view.calculator.Example

slagyr commented 12 years ago

You must be returning an instance of jack.view.calculator.Example from one of your handler functions. Compojure doesn't know what to do with those. Return a string or a response map.

On Oct 17, 2012, at 7:13 AM, yigitunlu notifications@github.com wrote:

This example returns No implementation of method: :render of protocol: #'compojure.response/Renderable found for class: jack.view.calculator.Example

— Reply to this email directly or view it on GitHub.