(この記事は、Clojure Advent Calendar 2011 21日目の記事です。)
前々からATNDでAPIが利用できることを知ってましたので、週末起業的な意味で、以下のサービスをHeroku上で作って見ました。当然Clojureです。
サービスの内容はブログのタイトル通りです。
http://find-event.herokuapp.com/users/tnoborio
作ったときに残したメモを頼りに、Herokuでどんな感じで作っていったかをさくさくっと書いていきたいと思います。
まずはLeinigenを作ってディレクトリを作成しますがそこらへんは割愛。
Herokuにアプリケーションを作るときに、--stack cedraを忘れずに作ります。アプリの名前を付けないと、flower-company-hogehoge-xみたいな名前がつくので最初から決めといたほうがいいです。
$ heroku apps:create --stack cedar find-event
http://clojars.org/repo/
その結果、project.cljはこんな感じになりました。
(defproject find-event "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.3.0"]
[compojure "1.0.0-RC1"]
[ring/ring-jetty-adapter "1.0.0"]
[fleet "0.9.5"]
[clj-json "0.4.3"]]
:dev-dependencies [[swank-clojure "1.3.4-SNAPSHOT"]])
前々からATNDでAPIが利用できることを知ってましたので、週末起業的な意味で、以下のサービスをHeroku上で作って見ました。当然Clojureです。
サービスの内容はブログのタイトル通りです。
http://find-event.herokuapp.com/users/tnoborio
作ったときに残したメモを頼りに、Herokuでどんな感じで作っていったかをさくさくっと書いていきたいと思います。
まずはLeinigenを作ってディレクトリを作成しますがそこらへんは割愛。
Herokuにアプリケーションを作るときに、--stack cedraを忘れずに作ります。アプリの名前を付けないと、flower-company-hogehoge-xみたいな名前がつくので最初から決めといたほうがいいです。
$ heroku apps:create --stack cedar find-event
それ以外にHeroku出動かすからという理由で必要だった作業はしProcfileを作る位でした。
こんな感じです。
web: lein run -m find-event.web
あとはgitを使ってガンガンプッシュしていきます。
$ git push heroku master
といっても、開発時はEmacs上でslimeつないで検証していく方が早くておすすめです。
プロジェクトを起ち上げた当初はproject.cljに必要なライブラリを追加して行く作業になりますが、clojarsからライブラリの最新バージョンを確認したり、どんなものがあるかというのを調べるのに最近では以下の直接のリポジトリから探すことが多いです。
その結果、project.cljはこんな感じになりました。
(defproject find-event "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.3.0"]
[compojure "1.0.0-RC1"]
[ring/ring-jetty-adapter "1.0.0"]
[fleet "0.9.5"]
[clj-json "0.4.3"]]
:dev-dependencies [[swank-clojure "1.3.4-SNAPSHOT"]])
Clojure 1.3はHerokuですんなり使えました。流石です。
以降コードの話になりますが、ATND APIを使いたいのでこんなコードを書きました。(一部抜粋です。)
(ns find-event.api
(use [clojure.walk :only [keywordize-keys]]
[clojure.string :only [join]]
[clj-json [core :as json]]))
(def events-url "http://api.atnd.org/events/")
(def users-url "http://api.atnd.org/users/")
(defn- fetch [url]
(-> (slurp (str url "&format=json"))
json/parse-string
keywordize-keys))
;; (fetch "http://api.atnd.org/events/?twitter-id=tnoborio")
イベントの検索、特定のイベントのユーザの取得、Twitter IDでの検索など、必要だと思った機能がそろってました。
例えば特定のイベントからユーザを取得するのはこんな感じです。
(defn- users-by-event-id [event-id]
(let [url (str "http://api.atnd.org/events/users/?event_id=" event-id)
users (-> (fetch url)
:events
first
:users)]
(map :user_id users)))
で、どうやってイベントをレコメンドするかというと、
- Twitter IDからそのユーザの参加イベント取得
- 取得したイベントに参加しているユーザ取得
- そのユーザたちが来月開催されるイベントで参加するものを取得
という流れです。Clojure的に->>を使ってそれを表したのが以下のコードです。
(defn suggest-events [twitter-id]
(let [entry-events (fetch-events :twitter-id twitter-id)]
(->> entry-events
event-users
(take 50)
(fetch-events :year 2012 :month 1 :users))))
みていただいて分かりますようにかなり手を抜いていて、もっとよくなるポイントはいくつもありますが、これだけのコードで面白そうなイベントが分かったので今日のところはオッケーとしました。
実際にもう少し作りこめば普段から使えるサービスになりそうです。
ちなみにClojureとは関係ないのですがデザインにはTwitterのBootstrapを使いました。Fleetを組み合わせましたが、デザインにかけた時間は5分くらいです。プログラマだけでサービスを作るのにBootstrapはおすすめです。
と、そんな感じでラフな記事になりましたが、皆様良いお年を、良いクリスマスを。
コメント