RingoJSのチュートリアルをやってみる


チュートリアルを見ながら、今日もRingoJSを触ってみます。

Webapp Scaffolding

Webアプリーションのひな型を作成するコマンドがあります。

$ bin/ringo-admin create apps/demoblog

上のコマンドを叩くと、「apps」ディレクトリの下に「demoblog」というディレクトリが作成されました。この中にWebアプリケーションのひな型が入っているのでしょう。ピヨピヨ。

apps/demoblogフォルダには3つのjavascriptファイルが入っていました。

  • main.js
  • config.js
  • actions.js

それから3つのフォルダがありました。

  • skins/
  • public/
  • config/

ringoコマンドにmain.jsを渡して実行するとサーバーが起動します。

$ cd apps/demoblog
$ ../../bin/ringo main.js
0    [main] INFO  ringo.webapp.daemon  - init
1008 [main] INFO  ringo.webapp.daemon  - start
1010 [main] INFO  org.eclipse.jetty.util.log  - jetty-7.1.6.v20100715
1143 [main] INFO  org.eclipse.jetty.util.log  - Started SelectChannelConnector@0.0.0.0:8080

昨日と同じようなログが出力されてサーバーが起動しました。
http://localhost:8080 で参照できます。

main.js

main.jsはwebアプリケーションを起動するスクリプトみたいです。
正直、何が書いてあるのかよくわかりませんが、このファイルを編集するのはまだ先でしょうからあまり考えないでおきます。

#!/usr/bin/env ringo

// main script to start application

if (require.main == module) {
    require("ringo/webapp").main(module.directory);
}

config.js

ミドルウェアとかデータベースとかアプリケーションそのものとか、その他いろいろな設定を書くファイルみたいです。
結構長いので少しずつ見ていきます。

// URL routing. Using require() here to statically import modules will
// improve performance, but may cause hard to debug cyclic module dependencies
// in case any app module requires this module.
exports.urls = [
    ['/', './actions'],
];

URLルーティングの設定みたいですね。親切にコメントが書かれていますが、、、読めません><。URL「/」が「actions.js」に対応するってことだと思います。

// Middleware stack as an array of middleware factories. These will be
// wrapped around the app with the first item in the array becoming the
// outermost layer in the resulting app.
exports.middleware = [
    require('ringo/middleware/gzip').middleware,
    require('ringo/middleware/etag').middleware,
    require('ringo/middleware/static').middleware(module.resolve('public')),
    // require('ringo/middleware/responselog').middleware,
    require('ringo/middleware/error').middleware('skins/error.html'),
    require('ringo/middleware/notfound').middleware('skins/notfound.html'),
];

ミドルウェアのスタック」と書いてあります。謎です。

// The JSGI application. This is a function that takes a request object
// as argument and returns a response object.
exports.app = require('ringo/webapp').handleRequest;

「JSGIアプリケーション」と書いてあります。謎です。

// Standard skin macros and filters
exports.macros = [
    require('ringo/skin/macros'),
    require('ringo/skin/filters'),
];

謎です。

// Default character encoding and MIME type for this app
exports.charset = 'UTF-8';
exports.contentType = 'text/html';

やっと謎じゃないのが出てきました。レスポンスのデフォルト文字コードとコンテントタイプですね。見覚えのある単語が出てきてやっと一安心です。データベースの設定とかするところがなかった気がしますが、今は気にしないでおきます。

actions.js

var {Response} = require('ringo/webapp/response');

exports.index = function (req) {
    return Response.skin(module.resolve('skins/index.html'), {
        title: "It's working!"
    });
};

「index」に関数が代入されています。関数はResponse.skin()関数に、ファイル(skins/index.html)と、置き換え文字列の連想配列{title: "It's working!"}を渡したものを返すみたいです。

ファイル(skins/index.html)も見てみましょう。

skins/index.html

<% extends ./base.html %>

<% subskin content %>
<div id="header"><h1><% title %></h1></div>
<div id="body">
<p>You just created a new Ringo application. Here are some possible next steps:</p>
<ul>
    <li>Tweak the URL routing or middleware stack in <code>config.js</code>.</li>
    <li>Edit and add actions in <code>actions.js</code>.</li>
    <li>Adapt the templates in the <code>skins</code> directory to your liking.</li>
    <li>Install one of the available <a href="http://ringojs.org/wiki/Packages/">database
        packages</a> to store application data.</li>
    <li>Visit our <a href="http://ringojs.org/wiki/Tutorial/">tutorial</a> or
        <a href="http://ringojs.org/wiki/Documentation/">documentation</a> to learn more about Ringo.</li>
</ul>
<p>Thank you for using Ringo!</p>
</div>

h1タグに囲まれて、置き換え文字列っぽい「title」の文字が見えますね。ここが置き換わるのでしょう。

「base.html」を継承しているようなので、これも見てみます。

skins/base.html

<!DOCTYPE html>
<html>
<head>
<title><% title %></title>
<link rel="stylesheet" href="/stylesheets/page.css" />
<% render head %>
</head>
<body>
<% render content %>
</body>
</html>

<% subskin content %>
Overwrite this subskin to add content.

テンプレート(index.html)が他のテンプレート(base.html)を継承して、subskin contentを上書きしている。っていう感じみたいです。

編集してみる

actions.jsを編集して、アクションを追加してみます。

var {Response} = require('ringo/webapp/response');

exports.index = function (req) {
    return Response.skin(module.resolve('skins/index.html'), {
        title: "It's working!"
    });
};

exports.test = function(req) {
    return Response.skin(module.resolve('skins/index.html'), {
        title: '動いたよ!"
    });
};

exports.testに関数をセットしてみました。そして置き換え文字列「title」を日本語にしてやりました。ファイルを保存して http://localhost:8080/test を開いてみると

日本語になりました。やったね!

サーバーを再起動しなくても変更が反映されました。これがInstant reloadingってやつなのでしょう。SAStrutsではhot deployとかhot reloadingとか呼ばれていました。

まとめ

無計画に試しながら書きながらしていたらまとまりがなくなってきました。まとめます。

RingoJSにはwebアプリのひな型を作るコマンドが付属している

$ ./bin/ringo-admin create [フォルダ]

コマンドを実行すると、以下のファイルとフォルダが作られる

  • main.js Webアプリを起動するスクリプト。ブートストラップ。中身はあまり気にしない。
  • config.js 各種設定を書くファイル。URLルーティングもここ。設定ファイルだけどJavaScriptソースコード
  • actiongs.js config.jsの中でURLに関連つけられている。レスポンスを返す関数を記述していく。MVCのView。

以下のフォルダも作られる

  • skins/ テンプレートファイル。actions.jsから読み込まれる?
  • public/ CSSとか、画像とか、(ブラウザで動作する)JavaScriptとか、静的コンテンツを置くフォルダ。
  • config/ webサーバの設定ファイル。「Don't worry」と書いていたので気にしないことにします。