本を読む

読書やコンピュータなどに関するメモ

clj-gae-blankでClojure + GAE/J

 引き続きTokyo.clj #2メモ。makingさんが、GAE/J(Google App Engine for Java)を使うためのライブラリ群と、それを使ったサンプルclj-gae-blank(名前に反して簡易ゲストブック)を公開しているので、中身を調べつついじってみる。

とりあえず動かす

必要なもの

  • Java
  • Leiningen
  • GAE-J SDK

プロジェクトをダウンロードしてリネーム

$ git clone http://github.com/making/clj-gae-blank.git
$ mv clj-gae-blank gb
$ cd gb
$ mv src/clj_gae_blank.clj src/gb.clj
$ mv src/clj_gae_blank src/gb

project.cljを編集

 名前だけ変更。

(defproject clj-gae-blank "0.1.0-SNAPSHOT" 
  :description "a blank project for clojure on GAE" 
        ↓
(defproject clj-gae-blank "0.1.0-SNAPSHOT" 
  :description "guestbook by clojure on GAE" 
  :namespaces [clj-gae-blank])
        ↓
  :namespaces [gb])

war/WEB-INF/web.xmlを編集

 「clj-gae-blank」と「clj_gae_blank」を「gb」に。

src/gb.cljの中身と編集

 メイン処理のソース。名前だけ変更。

(ns clj-gae-blank
        ↓
(ns gb
        [clj-gae-blank hello guestbook]))
          ↓
        [gb hello guestbook]))

 ちなみに、こんな感じ(↓)でCompojureでURLルーティングしている。

(defroutes app
  (GET "/greet" req (greet req))
  (GET "/*" _ (hello)))

(defservice app)

 Compojureのこのへんの仕様は変更が激しそう。

src/gb/hello.cljの中身と編集

 表示のアクション。hiccupを使ってHTMLを生成している。名前だけ変更。

(ns clj-gae-blank.hello
        ↓
(ns gb.hello
        [clj-gae-blank.guestbook]
          ↓
        [gb.guestbook]

src/gb/guestbook.cljの中身と編集

 投稿のアクションと、データストアまわり。名前だけ変更。

(ns clj-gae-blank.guestbook
        ↓
(ns gb.guestbook
        [clj-gae-blank.guestbook]
          ↓
        [gb.guestbook]

 ちなみに、同じmakingさんのclj-gae-dsを使ってデータストアに投稿内容を格納し、"/"にリダイレクトしている。あと、表示のときは、clj-gae-dsでデータストアから取り出している。

(defn show-greets []
  (for [x (take 20 (query-seq (-> (q "Greeting") (srt :date :desc))))]
    [:p (h (get-prop x :name)) " " (h (get-prop x :content)) " " (h (get-prop x :date))]))

ビルド、実行

$ lein deps
$ lein compile
$ dev_appserver.sh war

 ブラウザでhttp://localhost:8080/にアクセス。

clj-gae-blankほぼそのまま

 データストアがwar/WEB-INF/appengine-generatedの下に作られる。

情報: The backing store, /path/to/gb/war/WEB-INF/appengine-generated/local_db.bin, does not exist. It will be created.

Googleアカウント認証

 Googleアカウント認証を試すため、投稿するのにGoogleアカウントでの認証を求めるようにしてみる。

src/gb/hello.clj

 nsの:useに追加。clj-gae-usersライブラリは最初からproject.cljで指定されている。

        [am.ik.clj-gae-users.core]

 ユーザー名はGoogleアカウント入力から取るので、入力フォームのHTMLを生成するgreet-form関数のうち、名前の入力フォームを削る。

   "name:" [:input {:name :name :type :text}]
   [:br]   

 greet-form関数をラップして、認証しているかどうかで分ける関数を追加。user-logged-in?やcreate-login-url、create-logout-urlはclj-gae-usersのもの。

(defn login-or-form []
  (if (user-logged-in?)
    [:div (greet-form) [:p [:a {:href (create-logout-url "/")} "Logout"]]]
    [:div [:a {:href (create-login-url "/")} "Login"]] ))

 helloの中。

         (greet-form)
          ↓
	 (login-or-form)

src/gb/guestbook.clj

 同じくnsの:useに追加。

        [am.ik.clj-gae-users.core]

 投稿アクションのgreet。let中、名前をHTTPリクエストからではなく、get-current-user-map(clj-gae-usersのもの)を使ってGoogleアカウント情報から。で、letとその中のds-putをuser-logged-in?が真のときのみ評価するようにして、redirectはそこから出す。

(defn greet [req]
  (if (user-logged-in?)
    (let [content (get-in req [:params "content"])
	  name ((get-current-user-map) :nickname)
	  entity (map-entity "Greeting" :content content :name name :date (java.util.Date.))]
      (ds-put entity)))
  (redirect "/"))

コンパイル、実行

clj-gae-blankに認証(ログイン前)

 「Login」をクリックするとログイン画面に。

clj-gae-blankに認証(ログイン)

 SDKのローカルサーバーだと、パスワードなしで認証が通ったことになる。

 ログインすると入力フォームが表示される。

clj-gae-blankに認証(ログイン後)

ユーザー別の表示

 データストアとCompjureを試すため、特定ユーザーの発言だけをフィルタリング表示できるようにしてみる。

src/gb.clj

 URLルーティングに1つ追加。

  (GET "/u/:id" req (user-greetings ((req :route-params) "id")))

src/gb/hello.clj

 データストアから、ユーザー名に合致したものだけをシーケンスとして取ってくる関数を作る。show-greetsでの処理に「(flt "name" = user)」を追加。SQLのWHERE節っぽい。

(defn query-user-entries [user]
  (query-seq (-> (q "Greeting") (flt "name" = user) (srt "date" :desc))) )

 これを使ってuser-greetingsを実装。

(defn user-greetings [user]
  (html [:html
         [:head
          [:title (h user) "'s messages"]]
         [:h1 (h user) "'s messages"]
	 (for [x (take 20 (query-user-entries user))]
	   [:p (h (get-prop x :name)) " "
	    (h (get-prop x :content)) " "
	    (h (get-prop x :date)) ])]))

 hを使えるようにnsの:useを変更。

  (:use [hiccup.core :only [html]]
        ↓
  (:use [hiccup.core :only [html h]]

 で、ビルドして実行して、「http://localhost:8080/u/ユーザー名」にアクセスすると、そのユーザーの発言だけ表示する。ただし、"@"とかが入ったユーザー名は扱えないので、"@"とかが入ってない名前でログインして投稿する必要がある。

変更2010-05-09:投稿時のuser-logged-in?チェックが抜けていたので追加

コメント

コメントの投稿

管理者にだけ表示を許可する

トラックバック

http://emasaka.blog65.fc2.com/tb.php/758-25857632

 | HOME | 

Categories

Recent Entries

Recent Comments

Recent Trackbacks

Appendix

emasaka

emasaka

フリーター。
連絡先はこのへん

Monthly


FC2Ad