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

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

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

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

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

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

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

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

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

昨日の生放送@n0tsさんにscreenの便利な設定を教えてもらいました。

.screenrc

screen -t vi 1
screen -t zsh 2
screen -t db 3
screen -t repl 4
screen -t server 5
select 1

こう書くと、screenを立ち上げた時に自動的に5枚windowが用意されて1が選択されている状態になります。特に僕はwindow 0を使ってなかったし、かならず5毎立ち上げるのが癖になっていたのでとても便利になりました。

screen-4.0.3 — 80×24

それぞれのwindowの使い道も何故か自分の中で決まってるので初期タイトルにそれを付けておきました。

Integrityのコードにあったaタグの書き方。

%Q(<a href="#{page_data.last}">#{page_data.first}</a>)

"が書けるから楽なんですね。ちょっと嬉しい。

lib/integrity/helpers/breadcrumbs.rb at master from integrity's integrity - GitHub

'unk'.to_sym

って

:'unk'

こうも書けるんですね。知らなかった…orz

HashWithIndifferentAccessとかMashに慣れ過ぎてシンボルを疎かにしてると裏世界でひっそり幕を閉じる。(@ブロントさん)

:"u#{n}k"

こういう時便利。

CMS作成一人合宿最終日。

cssを書いてないので全然出来てないように見えるが機能的には最低限の機能が出来つつある。あと2日ぐらい作業すればこのブログを移行することが出来そうだ。

検索機能、ページング機能とWordPressでいうところのコンディショナルタグ機能を作った。 コンディショナルタグとは、テンプレート中で今どのページにいるのかを判断するために使う関数。

PyhaもWordPressの影響を受けて、複数のコンテキストを持つが全てに対応するテンプレートを用意する必要は無い。(対応するテンプレートが存在すればそちらを使う)

コンテキストとは、トップページだとかカテゴリーアーカイブとか個別ページとかそいう文脈のこと。

それぞれにテンプレートを用意するのは大変なので、最低限のテンプレートは、インデックスやアーカイブのように、複数のテキストを表示するdocumentsと、個別エントリーのように一つのテキストを表示するdocumentの2つだけだ。

  • documents.erb --- 複数のテキストを表示するテンプレート
  • document.erb --- 一つのテキストを表示するテンプレート

テンプレートをまるごと切り替える必要はないが、例えば一つのテンプレート内でタイトルだけはコンテキストに応じて変更したいという場合にコンディショナルタグを使う。

<% if category? %>
  <h2>カテゴリーページ</h2>
<% else %>
  <h2>トップページ</h2>
<% end %>

のように使う。

現状あるコンテキストにあわせて下記のコンディショナルタグを用意した。

  • index?
  • search?
  • category?
  • yearly?
  • monthly?
  • dialy?
  • document?
  • documents?

最後の2つはコンテキストではなく、テンプレートの種類を表すものなので、どれか一つのみがtrueを返すわけではない。例えばindex?とdocuments?は両立する。

(もちろんリリース後に書くドキュメントはこんな小難しい書き方はしない。今は自分の考えをまとめるためにメモする)

現状、例えばWebから投稿するインターフェースは無い。それはすぐ作れるが、テーマ作成者向けAPIが固まらないうちに細部をつくりはじめると、管理画面の実装上の都合などが無意識にAPIに影響を与えてしまうので、先にWordPressのブログを移行するのに十分なAPIを固めた上で作りたい。

先が見えてきたので残りタスクをリストアップしてみた。最初のバージョンは少ない機能でリリースしたい。

5日間一人合宿の感想

5日間かけた割には平均的なRubyistに比べて進みが遅いと思うが、正直、予想以上でも以下でもなく、まあこのぐらい進むだろうなと思っていた通りな感じだった。プログラムを作る方法としては結構はかどるやり方だと感じた。でも途中で@jishihaさんと作っているものについて話したのが非常に良かった。丸5日誰とも合わずに作っていたら機能は増えたかもしれないが、ソフトが良くない方向に進んでいたように思う。勉強会やカンファレンスも楽しいが、自分の作っているプロダクトに関するディスカッション程有益なプログラマー同士のコミュニケーションは無いと強く感じました。

タスク:Issues - komagata/pyha - GitHub

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

DataMapperパターンのRuby実装。RDB、KVS、NoSQL系DBをサポートしてて、1.0.0なので結構枯れてる。

調べる必要があったヤツだけをメモ。

スラッグ型(URLの中で使える文字列)

String型のサブクラスだから安心。

require 'dm-types'

Class Post
  include DataMapper::Resource

  property :slug, Slug
end

デフォルトスコープ

Class Post
  include DataMapper::Resource

  property :id, Serial

  default_scope(:default).update(:order => [:id.desc])
end

手抜き全文検索

Class Post
  include DataMapper::Resource

  property :id, Serial
  property :title, String
  property :body, Text

  def self.search(str)         
    all(:title.like => "%#{str}%") |
    all(:body.like => "%#{str}%")   
  end
end
Post.search('unk').all(:limit => 5)

「でたー!クラウザーさんのLIKE '%foo%'だー!」

真面目にやるならdm-is-searchableでインデックスを別のストレージ(DM用語ではrepository)に保存する。

サインアップとログインを作った。

Admin Loginからuser:pass = test1:testで入れる。

ユーザー認証にはsinatara-authenticationというgemがあるが、100行足らずで実装できる部分だし、DataMapperの時点であらゆるDBに対応してるのにそのORM自体を差し替えられるというのはCMSにはオーバースペックなので外した。

sinatra自身もそうだが、ライブラリやフレームワークの癖が強すぎるとCMSとして一貫したAPIを作るのにどうしても思想的な偏りが出来てしまって良くないように思う。(例えばRailsをベースにCMSを作るとRails流儀に合わせようという心的姿勢が無意識に出来てしまう。)

sinatraはそういった癖がかなり少ない方だが、極限までミニマルなCMSを作りたくなる衝動を抑えるのは難しい。

何度かsinatraアプリを作った経験とミニマルになりすぎて実用的でないアプリを量産した苦い思いがなければまた同じ過ちを犯したに違いない・・・。

sinatraも1.0.0が出て、そろそろコミッタもユーザーもクールダウンしているのであくまで裏方として使う良い頃合いなのかもしれない。

管理画面をちょこっと作ってみて、イケそうなので細部はほっておいて、表側のテーマ作成者向けのAPIをきちんとつくっていきたい。

WordPressのデザイナーから見た利点は@machidaさんに事あるごとに質問して来たんだが、下記のサイトを見て、「WordPressでイケル!」と確信を持ったそうです。

WordPressテーマ(テンプレート)カスタマイズのまとめ(日本語訳) - TRANS

これを参考に、「クラウド対応の一貫したテンプレートAPIを持つCMS」というコンセプトが達成できるように作って行こうと思います。

今日は一人合宿ではありませんでした。@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

標準ライブラリのDateで月の加減計算が出来るって知ってました?

Ruby、3年以上はやってるはずなのに知りませんでした…orz

+, -で日の加減が出来るのは直感的にわかるけど、月に対しても出来るとはびっくりしました。

% irb -r date
>> (Date.today).to_s
=> "2010-08-15"
>> (Date.today << 2).to_s
=> "2010-06-15"
>> (Date.today >> 5).to_s
=> "2011-01-15"

サブクラスのDateTimeでもモチロン出来ます。

オーマイガッ!

とりあえずHerokuで動かしてみた。

Test Site

Herokuのbundlerが1.0.0.rc.2に上がってて糞ハマる。

CMS本体のコードよりも、テーマ作成者向けのAPIを慎重に吟味する。

テーマファイルは下記のような構成にした。

  • posts.erb --- 複数の投稿を表示するページ。(トップページ、アーカイブ、検索結果など)
  • post.erb --- ひとつの投稿を表示するページ。(個別ページ)
  • index.erb(必須でない)--- トップページ。このファイルが無い場合はposts.erbが使われる。
  • layout.erb(必須でない)--- レイアウトファイル。このファイルが無い場合はレイアウト機能は使われない。
  • style.css(必須でない)--- CSS。