pyhalokkaに名前が変わりました。公式サイトのURL、リポジトリの場所もかわりました。

貧弱一般プロジェクト(@ブロントさん)であるpyhaですが、もし興味があるという方ががいれば分り易いようにコードが大体どんな感じなのか書いておこうと思います。(pyhaは名前を見たら殆どの人はpython製だと思うということに大分後になって気付きました・・・)

基本、sinatra, datamapper, hamlです。あとは動かすためのbundlerです。

ファイルレイアウト

ファイルレイアウトはいわゆるsinatraの"Moduler"スタイルで、sinatraやったことがある人だったら、「ああ、コレか・・・」ってなもんです。

Gemfile      --- bundlerが読む必要なgemの一覧
config.ru --- rackサーバーが最初に見るファイル
lib/
pyha.rb --- 今のところ特に何もしない
pyha/ --- 基本全部この中。将来的にはgemの中に入るハズ
app.rb --- 中心部分。ここ見りゃ大体わかる
helpers.rb --- rails風のヘルパー以外にapp内でのユーティリティも含む
before.rb --- リクエストされたときの前処理
entry.rb --- DataMapperのモデル。他にもいくつかある。
public/ --- ドキュメントルート
admin/ --- 管理画面
system/ --- エラーとかシステムで使うテンプレ
theme/ --- テーマ。現状テーマ名=この下のディレクトリ名
default/ --- デフォルトテーマ。erbでWordPress経験者のデザイナーに優しくをモットーに。
p0t/ --- docs.komagata.orgのテーマ。hamlでなるべくDRYに書く。プログラマー向け。
plugin/ --- プラグインはsinatra extensionのサブセット
hello --- plugin以下のディレクトリ名=プラグイン名
lib/ --- 各プラグインディレクトリ以下はgem化を見越してgemのレイアウト準拠
pyha/ --- 一応、pyhaネームスペース以下にする
hello.rb --- Pyha::プラグイン名というclass or moduleが読み込まれるという決まり

普通のModulerスタイルにhelpersとbeforeを別ファイルにしたってだけです。

テーマレイアウト

テーマ(テンプレートの集合)はWordPressでテーマを作ってるようなデザイナーを想定していて、そういう人がWordPressより一貫した分り易いsyntaxで簡単に書けるように注意しています。

entries.erb(必須) --- 複数のエントリを表示するテンプレート
entry.erb(必須) --- 1個のエントリを表示するテンプレート
layout.erb --- 外枠を表示するテンプレート
index.erb --- トップページを表示するテンプレート
search.erb --- 検索結果を表示するテンプレート
category.erb --- カテゴリー別エントリ一覧を表示するテンプレート
tag.erb --- タグ別エントリー一覧を表示するテンプレート
yearly.erb --- 年別エントリー一覧を表示するテンプレート
monthly.erb --- 月別エントリー一覧を表示するテンプレート
style.css --- CSS(読み込める場所にあればどこでもいい)
screenshot.png --- テーマ選択画面に表示される画像

必須のモノ以外はそのファイルが存在する場合はそちらを優先するようになっています。例えばentries.erbとindex.erbが両方あったらトップページにアクセスした場合、index.erbが表示されます。また、テンプレ無いでのpartialは好きに出来るのでheader.erbとかfooter.erbとか好きに作れます。また、erb, haml, erubisの3種類のテンプレートが使え、拡張子で判断されます。erb, haml, erubisの順に優先度があり、entry.erbがあるとentry.hamlは使われません。

モデル

モデルはDataMapperのをそのまま使っています。自動的にテーマデザイナー向けAPIに一貫性が出来ます。

entry    --- エントリー。サブクラスは増える可能性あり
post --- 投稿。pageとの違いは各種テンプレにデフォルトでassignされてるかどうかだけ(例:@posts)
page --- ページ。CMS的に好きなページを作る場合に使う
site --- このサイト/ブログ自体の情報
user --- ユーザー。そんなに使わない
category --- ツリー構造を持つ。エントリが持つcategoryはひとつだけという制約があるのはパンくずリストを生成するため
tag --- categoryの制約が無い。パンくずリストが無ければtagだけでも問題無いんだが・・・
comment --- いわゆるコメント。どうせdisqusとか使うだろうと思って軽視していた

プラグイン機構

プラグインはSinatra Extensionのサブセット(ココ参照)なので楽です。プラグインの決まりは上記のコードレイアウト通りですが、まだplugin以下に置いてあるものを自動で読み込む処理を書いてません。(すぐ書けるけど貧弱なcoreの改良に忙しいだけです・・・)

クラウド対応ツールとしての注意点

  • ファイルのWriteが出来ない環境(GAE, Herokuの殆ど)を考慮する(具体的にはローカルに画像をアップできない)
  • RDBだけでなく、KVS, ドキュメント指向DBも考慮する(具体的にはSQL使えない)
  • 海外に人にも使ってもらうために、publicなところには全て英語を用意する。(commitログ、BTSなど)

その他

WordPressに比べてApache, MySQLが要らないので何気にRubyはWindows環境に向いている。

開発への参加方法

とにかく誰でもwelcomeです。「インストールした」ってブログに書いていただけるだけでもありがたいです。

  • MLで改善案を言う
  • BTSにバグ登録する
  • インストールしたとブログに書く。Twitterでつぶやく。
  • githubでforkし、pull requestする
  • MLやgithubにpatchを送る
  • 公式サイト(http://pyha.cc/)のドキュメントを書く(言ってもらえれば公式サイトのpyhaユーザーのアカウントを発行します)
  • 公式サイトの英語ドキュメントを書く(マジで助かります…)
  • テーマを作る
  • プラグインを作る

基本、コード書いてやってもいいという方にはgithubのコラボレーター権限をホイホイ渡しますのでチマチマpull requestが面倒な方はMLやtwitterでおっしゃってください。

irc.freenode.netに#lokkaと#lokka-jaというチャンネルを作りました。(#lokka-jaの方は日本語で話す)

pyha (irc.freenode.net)

  • インストールしてみた
  • インストールできない
  • 改造してみた
  • ここバグってる
  • lokka.orgのドキュメント(日本語 or 英語)を書いてくれる方

などいらっしゃったらJoinしていただけると嬉しいです。

  • WordPressのPHPプラグインを書くのにウンザリしていたRubyistの方
  • 「the_post()ってなんだよ!」と思ったことがある方
  • HerokuかわいいよHerokuという方
  • 無駄にスケールするCMSが欲しい方

におすすめです。

ihara.jpg

ブログツール・CMSを作ってるんですが、どういう人の為に作っているかというのを考えてて、はっきりしなかったので図にしてみた。

図にしたらハッキリしました。

要は、テーマデザイナを重視したい。テーマデザイナとはブログツール・CMSの独自のテーマを作ったり、プラグインを作成したりするサードパーティのことです。

リスペクトして作っているWordPressでとても良い点が、テーマデザイナに優しいところでした。そこをもっと推し進めたい。

テーマデザイナに優しいとは要するにテーマAPIが分り易い・便利だということです。

テーマデザイナから見えるのは外側のテーマAPIだけで、コア内部の実装は見えません。なのでコア内部の実装の複雑さを犠牲にしてもテーマAPIを簡単にしたいと考えて作っています。

まあコアの実装なんかは基本僕だけなので僕が苦しめばいいと思っています・・・。

この図の更に外側にいるはずのブログを見に来る"閲覧者"がどうみても最優先なハズですが、fc2でもvicunaテーマを適用すれば他のブログと区別が付かない昨今、閲覧者にとっての各ブログツールの差は無いといって良いんじゃないでしょうか。

あとは、ブログの記事を書く"ユーザ"ももちろん大切です。しかし僕らがWebサイト制作で生じた要求(不満とも言う)を元に作り始めたツールなので(僕らもWordPressからみたテーマデザイナだった)、一番大切にしたいのは同じWebサイト制作者です。

今日は一人合宿ではありませんでした。@jishihaさんからアカデミーヒルズで作業してるので来ませんかというメッセージをもらったので行ってきました。(アカデミーヒルズは会員の同伴者として行くと安く使える)

以前も使わせていただいて快適だったので行くと、土日は同伴者駄目らしい。

ということで、Twitterでの@milkcocoaさん情報により、六本木地下鉄出口付近のルノアールに移動。無茶苦茶空いてるし、電源は使えるしで最高。

というか、お盆で、今日は花火という時に誰も仕事などしないのでルノアールはすいていた。

皆がお盆休みを満喫している間に僕らはモクモクとプログラミングした・・・。

CMSの進捗

昨日、面倒だったユーザー認証を終わらせたので、次に面倒だと思っていたツリー構造を持つカテゴリー機能を作った。幸いdm-is-treeというdatamapperのプラグインが殆どの面倒な部分を片付けてくれた。(DOMのように、parent, children, siblings, ancestorsなどのメソッドがある。特にancestorsがあればパンくずリストが簡単に出来る)

ついでに年別アーカイブ、月別アーカイブ、日別アーカイブも作った。group byなどのSQLを使ったらKVSにも対応してる意味が無くなるのでちょっと面倒。

デザイナーに使ってもらう工夫について

WordPressにある機能の実装にはさして問題なさそうだが、@jishihaさんとどうやったらエンジニア以外に使ってもらえるかについて色々話した。

WordPressのテーマをこのCMSを用に変換できるようにしたらどうか、とか、GUIインストーラーを作ったらどうかなど。

尖ったプログラマーがやらない地味なサイトやドキュメント整備が大事だという点は頑張ろうと思いました。

テストサイト:http://pyha.heroku.com/

ソース:komagata's pyha at master - GitHub

一人合宿1日目。CMS、とにかく作り始めました。

目標はデザイナーの方でも使える、クラウド環境対応(要はGAEとHeroku)のCMSです。

要はWordPressです。WordPressをクラウド対応(要はRDB、KVS、noSQL他DB対応)するのは相当難しい(出来てもデザイナーが使えるようなものにならなさそう)という結論からRubyで作ることにしました。

ツール自体はほぼ使ったことあるのを使うので技術的なチャレンジはしない予定です。Sinatra, DataMapperとかを使って、テーマ・プラグイン機構のあるCMSを地味に作る感じ。Windowsでの動作も必須で行きたい。

僕個人の趣味はなるべく我慢して、面倒な機能も頑張って実装しようと思います。

何でCMS作りたいかというと、WordPressが凄い便利だなーと思うからです。

デザイナー(@machidaさん)とプログラマー(俺)で会社をやってますが、デザインがメインの会社なので当然デザインの案件が多いです。そうすると、WordPressがあればプログラマーは何もしなくていいという案件がとても多いんです。

@machidaさんがWordPressを使い込んでるということもあるんですが、プログラマー無しでまともなWebサイトが作れるとかWordPress凄いなー。嫌だなー 怖いなー 怖いなー って思ってたんです。(褒め言葉)

でもまあ、時々はそのサイト向けに特化した機能や動きが必要になって、既存のプラグインでは対応出来ない時、プログラマー(俺)がプラグインをPHPで書くんですが、これが辛い・・・。

また、既存のプラグインで対応できるかの調査でそのプラグインのコードを全部読んだりするんですが、これもシンドイ・・・。(プラグインの作者がヘボイとかそういうわけでは全然無く、PHPとWordPressのルールと流儀をしっかり守ると逆にシンドイコードになるのです・・・)

それは我慢しろって話ですが、PaaS環境(GAE, Heroku)で動かないのがかなりダルイ。

WordPress用にさくらインターネットの500円の共有レンタルサーバーを借りるのがお決まりのコースなんですが、WordPress以外は全部Herokuに置くようになってから、@machidaさんが、

「何でWordPress、Herokuで動かないんですかねえ」

と、キレそうになっているのでHerokuで動くWordPress的な物が欲しいのでCMSを作ります。

最近仕事でWordPressのテーマやプラグインのコードに触れています。

WordPressには「結果を標準出力に出力する」か「返り値(文字列)として返す」かというフラグを引数に持つ関数がとても多い。

下記のコードは同じ動きをする。(実際にthe_titleの上記フラグは第三引数ですが分かりやすくするために簡略化しています。)

// エントリのタイトルを出力する
<?php the_title(); ?>
komagata [p0t]

<?php echo the_title(false); ?>
komagata [p0t]

本体にこういう関数が多いため、プラグインでも暗黙的にその動作を求められる。

何で後者がデフォルトじゃないのか。そもそも、

// エントリのタイトルを出力する
<?= the_title() ?>
komagata [p0t]

こうじゃ駄目なのか?

これはショートタグがマナー違反とされているため、<?php echoと書くのが面倒でこうなっているんではないでしょうか。

そもそも何故ショートタグが色々なコーディング規約で非推奨になっているのかも理解出来ない。XML宣言と同じ事はそれ程問題なんだろうか。何かセキュリティーホールがあるのかな?

テーマの中で<?php echo とわざわざ書かなければいけないせいで、テンプレートがウリのPHPの良さが損なわれている気がしてならない。

WordPressではthe_xxx()という名前だからといって必ず上記の機能を持っているわけではない。そもそも返り値を返さない関数も多い。

リファレンスを見ると、最近のバージョンになるにつれてthe_xxx()は関数内で出力、get_the_xxx()は文字列として返り値を返すというルールが出来つつあるっぽいが統一されそうな気配は無い。

この手の瑕があちこちに見られます。大勢に使われることで成長してきたソフトウェアだから仕方のない事だと思います。しかし、もう大きく舵を切らないとマズいところに来ていると感じました。

特に安価なレンタルサーバーで動くことが大きな長所であるWordPressは無料からあるクラウド環境に対応出来ないと今後生きていけないと思う。

それにはデータベースの抽象化がほぼ必須だ。このまま生SQL CREATE文を抱えた大量のプラグインと一緒に沈没していく危険性が高い。

僕の考えたWordPress生き残り戦略

  1. 今のAPIは期限付きDeprecatedで残しつつ、クリーンでデータベース非依存のAPIを作る。(本家がやらなくても、プラグイン制作者用ライブラリを作るでも良い)
  2. PHP4の排除運動に便乗して一緒に旧API依存プラグイン/テーマを推奨しない運動を広める。(新APIへ対応するプラグイン/テーマ開発者・ユーザーをAutomattic社とか作者のMattとかが賞賛しまくる。)
  3. プラグイン・テーマのバージョンを見て、管理画面で嫌な警告を出す。
  4. 1〜2年後ぐらいに旧APIを削除(ドーン!)
  5. ユーザーはいつの間にかクラウドに対応してる。

地味で当たり前で退屈な方法だけど今はじめないと手遅れになると思いました。

お客さんからクローラーにメアド取られたくないという要望があったので以前のエントリ内容をWordPressのプラグイン(ショートコード)にしてみました。

[caesar-cipher komagata@gmail.com]

こう書くと、

こういうJSが吐かれて、

メアドが表示される。

紀元前の人でも簡単に解読できますが、とりあえずクローラーにわからなきゃいいかなということで・・・。

更新:wordpress.orgのsubversionで管理するのが普通っぽいのでGithubの方はやめて本家に登録しておきました。

WordPress › Caesar Cipher « WordPress Plugins

関連:JSシーザー暗号でお手軽メアド隠し - komagata [p0t]

jquery.unk.jsプラグイン。

(function($){
$.fn.unk = function() {
$(this).text('unk')
return $(this) // 一応Chain出来るようにしとく
}
})(jQuery)
<html>
<head>
<title>jQuery Plugin Sample</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script src="jquery.unk.js" type="text/javascript"></script>
<script type="text/javascript">
$(function(){
$('body').unk()
})
</script>
</head>
<body>
</body>
</html>

結構簡単に書けちゃうんだね。仕方ないね・・・。

jQuery Plugin Sample

デモ:jQuery Plugin Sample

Rails検証報告書: プログラマの思索

Railsで特徴的なのは、CookieでHTTP セッションを管理できることだろう。

ここの仕組みが非常に分かりやすい。

Railsの後から付いた機能で一番素敵だと思うのがこの機能です。

「Cookieなんて仕様上は4KBしか保存出来ないんだから寧ろ弱体化してね?」

とか認識されることが多い気がしてならない。

コレ、導入時にも度肝を抜かれて、以降常に、

「ハンパねー、マジCookieセッションハンパねー!」

と脳内のアフロの人が言ってるんですが、大した利点に感じる人は少ないのか、他の言語やWAFで全面採用している例を見たことが無い。

Cookieセッション

そもそもセッションという言葉自体が複数の処理をまとめた単位という広義の意味とWebアプリケーションで複数リクエストにまたがってサーバー側に保存されるデータという狭義の意味が混在して使われているという事情があってWeb上でのテキストコミュニケーションを阻害している。

RailsのCookieセッションと言った場合は広義のセッションだが、狭義のセッションは存在しないと断言すると分り易い気がする。

RailsはHTTP(RESTアーキテクチャスタイル)の原則に従う形で何も共有しないという設計上のポリシーを持っている。

そもそもCookieと言う仕様はステートレスなHTTPプロトコルに広義のセッションを構築する上でNetscapeが考え出した上手い抜け穴だ。

CookieのデータはHTTPヘッダーに記載されて全データが送受信される訳だからHTTPリクエストの内容だけで全ての情報を表現するという原則からはみ出していない。

狭義のセッションに関しては言語仕様やアプリケーションサーバーの実装に委ねられていて、例えばPHP(言語仕様に狭義のセッションが含まれている)とJavaのTomcatとでは全然違う。

殆の実装でそうなっているんだけど、Cookie内の一意のIDをキーにしてサーバー上に(メモリであれ、ファイルであれ)狭義のセッションデータを持っている。

単体のHTTPリクエストやレスポンスで全ての情報を表現できなくてはHTTPの原則であるステートレスとは言えない。(Cookie内のIDがサーバー上のセッションデータを対応しているとしてもそれは単体のHTTPリクエストやレスポンスだけで判断出来ない、/tmp/sess_IDファイルの中にシリアライズされてるとかいった暗黙のルールが含まれている。)

RailsのCookieセッションは広義のセッションの維持はCookieによってのみ維持され、クライアントPCに保存され、それを元にしてステートレスなHTTPリクエストとして送出される。

認証

Rails2.x以降、Cookieセッションに移行すると同時に、認証は「restful_authenticationプラグインを使ってね!」という風にあっさりと変わった。

これは使う側やユーザーにとっては大した違いに見えないが、内部的には認証方式がBASIC認証に変わっている!

これまたファイルやDBに保存するステートフルな認証からステートレスな認証に思い切り変わっている。こんなもん土台をそっくりすり替えちゃう程の大変更だと思うんだけど、上位レイヤーに住んでる人には殆気付かれずに行った。

AtomPP策定のIETFの話し合い内でもあった、「APIと認証関係ねーだろう。認証はHTTPプロトコルの仕事」という身も蓋もない結論をあっさり採用する。そこに痺れる、あこがれる!

HTTPの原則を守る利点

ここまで過激にHTTPの原則を守る最大の利点は、Railsの設計方針としても上げられている「何も共有しない」からもわかるように非常にスケールアウトし易いところだ。そもそも、HTTP(の元のRESTアーキテクチャースタイル)はWebのような大きな分散環境を想定して作られたものである。

シンプルかつスケーラビリティの高いシステムを作るにはREST原則に従うのは理にかなっている。

何故ドラスティックな変更が可能なのか

Ruby界隈では標準仕様を決めてから実装するのではなく、「勝手に実装して、良いものだったら標準にしようか」というノリというか文化がある用に思う。

言語や周辺ツール・ライブラリの整備によって使い物になる実装が出来るまでの時間が恐ろしく短いため、整った仕様よりも、動くコードや自動テストが重視される傾向があるため、時間のかかる抽象的な議論が少なめになるせいではないだろうか。

例としては、最近各言語でxSGIと呼ばれてる仕様も通常、仕様とリファレンス実装を明確に分けるところをRubyではRackが実装を持って標準仕様を決めてしまった。そして実際にRack::RequestとRack::Responseはデファクトとしてあっという間に広まった。

不満

何が俺にこんな長文を書かせるかというと、

「Cookieセッション、BASIC認証を他の言語・環境でも使いたいんだよ!面倒臭くて仕方がない!」

というストレスが爆発したからである・・・。