Caveman kills ruby on rails - Chapter 1

Meta info

対象読者

NOTE

筆者はcavemanを捨てsnoozeを使うようになった。 詳細はここに記してある。

Introduction

本稿は原著の各章をCommon Lispに翻訳するシリーズの第一章である。 本章では開発環境構築とcavemanの簡単な導入紹介を行う。

Cavemanの概要

Cavemanとは

Common Lisp製のWebアプリケーション用フレームワークである。

Caveman開発環境の構築

OS

筆者のお気に入りのDAW(samplitude)はwindowsしかサポートしてないので、OSはwindowsである。

IDE

windows最強のIDEはVMwareである(次点でVirtualBox)。 筆者はこれにlubuntuというプラグインを入れて使っている。

roswell

処理系の管理にroswellを使用する。 インストール方法はここを参照。 lubuntuでros setupを行うとエラーを吐くがインストール自体は無事終わっているらしく(おそらくは)問題ない。

Editor

筆者はvimを愛用している。 vimとLisp処理系との連携にはvlimeがある。 が、筆者はより原始的な方法を取っている。 tmuxで端末画面を分割し、rlwrapで処理系を直接バチバチ叩くというものだ。

rlwrap -m ros run

これでカーソルキーによる、入力のヒストリ参照ができる。 複雑なコマンドの入力には不向きかもしれないが、Ctl+^でEditorが立ち上がるので、それでなんとかする。

このアプローチのメリットは複雑な操作を覚える必要がないことだ。 デメリットは処理系を直接叩いていることだ。 すなわちリモートの処理系にアクセスするというのができない。 その必要がでてきたなら、vlimeなりlemなりを覚えようかと思う。

caveman

REPLを立ち上げたらcavemanをインストールする。

(ql:quickload :caveman2)

アプリケーションの新規作成

以下のコマンドでプロジェクトスケルトンを作る。

(caveman2:make-project #P"~/roswell/local-projects/your-app" :author "Your Name")

your-appにはお好きな名前をどうぞ。 本シリーズではyou-appで通す。 パスも任意の作りたいところで大丈夫。 ここでは“~/.roswell/local-projects/”に作ることとする。

Cavemanを動かしてみよう。

アプリケーションはスケルトンが作られただけなので、REPLにロードする必要がある。

(ql:quickload :your-app)

サーバーを立ち上げるには以下のようにする。

(your-app:start)

これでlocalhost:5000に適当なブラウザでアクセスすれば良い。

サーバーを終了するには以下のコマンドを評価する。

(your-app:stop)

開発の前に。

アプリケーション開発中は予期せぬエラーを起こしてしまうことはままある。 クライアントからサーバにアクセスしようとしてサーバがエラーを吐いた場合、クライアントはサーバからの返信をタイムアウトまで待ち続けることになる。 これは著しく不便なので代わりにエラーメッセージを返すようにしよう。

ASDファイルの該当部分を以下のように編集する。

  :depends-on ("clack"
               "lack"
               "clack-errors" ; <--- This!
               "caveman2"
               "envy"
               ...)

次にapp.lispの該当部分を以下のように改変する。

(funcall clack-errors:*clack-error-middleware* ; <--- This and...
(builder
 (:static
  :path (lambda (path)
          (if (ppcre:scan "^(?:/images/|/css/|/js/|/robot\\.txt$|/favicon\\.ico$)" path)
              path
              nil))
  :root *static-directory*)
 (if (productionp)
     nil
     :accesslog)
 (if (getf (config) :error-log)
     `(:backtrace
       :output ,(getf (config) :error-log))
     nil)
 :session
 (if (productionp)
     nil
     (lambda (app)
       (lambda (env)
         (let ((datafly:*trace-sql* t))
           (funcall app env)))))
 *web*)
:debug t) ; <--- This!

これでサーバがエラーを起こせばクライアントにスタックトレースが表示されるようになる。

ルーティングの設定

ルーティングはsrc/web.lispに記述する。 デフォルトで以下のコードが書かれている。

;;
;; Routing rules

(defroute "/" ()
  (render #P"index.html"))

#P"index.html"の所在だが、これはyour-app.config:*template-directory*を参照している。 ここでは~/.roswell/local-projects/your-app/templates/がそれに当たる。

ビューの作成

#P"index.html"の中身を以下のように編集する。

{% extends "layouts/default.html" %}
{% block title %}Welcome to Caveman2{% endblock %}
{% block content %}
<h2>Hello</h2>
<p>Here we go.</p>
{% endblock %}

ブラウザをリロードすると変更されているはずだ。

変数の表示

上述のdefrouteを以下のように変える。

(defroute "/" ()
  (render #P"index.html" '(:message "Hi!")))

その上で`#P“index.html”を以下のように変える。

{% extends "layouts/default.html" %}
{% block title %}Welcome to Caveman2{% endblock %}
{% block content %}
<h2>{{message}}</h2>
<p>Here we go.</p>
{% endblock %}

htmlファイルの変更はブラウザのリロードだけで反映されたが、Lispソースを改修した場合はプロジェクト自体をリロードしないと変更は反映されない点要注意。

(ql:quickload :your-app)

プロジェクトのリロード後にブラウザをリロードすれば変更が反映されているはずだ。

まとめ