Archive for August 2008
やはりこれだと面倒なので,ネスト付きパーサーに切り替えることを画策中です。
ただ,単純に切り替えただけではさすがにエラーが…。ちゃんとテストしていないメソッドなので当然ですが。しばらくバグ取りに時間がかかりそうです。
それと,このネスト付きパーサーを考えたときは,ネストの内側も全部解釈実行することを前提にしていたのですが,考えてみたら内側は別のパーサー(例えばスキン変数の内側はテンプレートのパーサーが扱うべき)で実行するのが普通なので,そのあたりの処理も変えないといけません。例えばifの解釈もネストできるのですが,そこはオーバースペックでしょう。


おおむね好評だったといっていいと思うのですが,Ruby on Railsを使っていることについてはやはり賛否両論分かれました。実績が少ないことでの不安に加え,現在のところホスティングで使えるところが限られてしまうのが理由だと思います。
ただ,PHPやMySQLも5,6年前には安くて使えるところはほとんどありませんでした。Nucleusの最初のバージョンがでてきたころはPHPが広がった時期とほぼ同じではないかと思います。
Railsも後1年くらいでそれくらいのところまで来るのではないかというのが僕の予想です。
ほかにはHTTPの認証について,やはり意見が分かれました。ここも仕方ないところだと思いますが,Foodynではプラグインで別の認証が使えるようにしておく(はず)なので,大きな問題にはならないのではないかと思っています。
限られた時間でのプレゼンだったので,RESTにまつわるところなど説明が足りていない部分もかなりあると思いますが,それでもこれだけ理解してもらったことはありがたいことです。
昨日書いたsafeスキンのフィールドも含めてちょっとテーブルをいじらないと。
テーブルいじること自体はMigration書くだけなので簡単なのですが,Migrationがあんまり多いと配布するときは格好悪いので,どこかでマージして数を減らす必要があります。そうすると既にインストールしている人にテーブルをいじってもらわないといけなくなるなど,また別の面倒が出てくるのが鬱陶しいところ。
先日のプレゼンでは時間の関係でさらっとしか話しませんでしたが,Foodynではスキン・エンジンに「safe」あるいは「unsafe」の属性が付きます。デフォルトのNucleus互換エンジンは「unsafe」なので,「safe」なスキンしか使えないユーザーはアクセスできません。そこで,Nucleus互換のエンジンを使った「safe」なエンジンが必要になります。
このエンジンでは,ユーザーはスキンの選択はできますが編集できません。indexページに表示するアイテムの数だけが設定できます。
この程度のエンジンだったら簡単に作れますし,イメージつきやすいかなあと。
インライン・テンプレートはスキン変数のパラメータに{}で挟まれた部分があると,そこをJSON(実際にはYAMLのライブラリを使っていますが)として解釈するもの。まだちゃんとデバッグはしていませんが,たぶんそんなに問題はないでしょう。
Foodyn CMSについてはこのブログにいろいろ書いてはいますが,見ていない人も多いだろうし,情報がまとまっていないので,この機会にどういうものだか理解してもらおうと,時間を取ってもらってプレゼンさせてもらいました。前の記事のプレゼンはそのための資料です。
午前中に1回と,見逃した人用に夕食後に1回,計1時間近く使わせていただきました。ありがとうございました。これが何かのきっかけになればと思います(Sourceforge.netのDevelopersは一人増えました。^^)。
また,ページスイッチの部分を実装しました。一つのページの中に複数の切り替え用スイッチ(例えば一つはメインブログ,もう一つはサブブログの切り替え用)を置けます。実装は案外苦労しましたが,割と面白い機能になったかと思います。
これらを使うと最低限のスキンを作ることがこれまでよりかなり簡単になるだろうと思います。
インライン・テンプレートの機能を加えれば,スキン編集一つだけでも済ませられるようになります。
RESTfulについてはyohei-y:weblogのREST入門やリコーの研究部門によるドキュメントが分かりやすくまとまっています。またRailsにおける実装についてはRuby on Rails勉強会で翻訳したものが簡潔にまとまっています。
ここではさらに簡単に言うとRESTはリソースをURLで表現し(例えばhttp://example.com/blog/a/item/b でブログaのアイテムbをあらわす),HTTPのverb(GET,POST,PUT,DELETE)でそれに対する操作を決めます。例えば,前述のURLをGETするとブログaのアイテムbを表示し,PUTすると内容を更新し,DELETEすると削除します。実際にはPUTとDELETEは現在のWebブラウザがサポートしていないので,RailsではPOSTとhiddenなフィールドを使って擬似的に実現しています。前述の勉強会の記事ではRESTの操作とRailsで呼び出されるコントローラのメソッドの関係が記述されています。
RESTを使うメリットとしてはリソースと操作が分離されて分かりやすくなること,副作用が伴う操作でGETを使うことはないこと,「ステート」がないためスケールしやすいこと,があります。RESTではHTTPのプロトコルですべてが表現されるというのが基本なのでクッキーも使いません。認証はBASIC認証やDIGEST認証といったHTTP標準でブラウザがサポートしているものを使います。
具体例で示します。Foodynの管理画面では,最初に開いたときにblogのindexを表示します。そこからブログaのアイテム一覧を表示するのはblog/a/itemsというリソース(itemが複数形になっていることに注意)をGETすることです。ブログaに新規アイテムを作るには最初にblog/a/items/newをGETして新規入力用フォームを表示します。入力後blog/a/itemsにPOSTすることにより,新しいアイテムができます。また,ブログaのアイテムbを編集するにはblog/a/items/b/editをGETして,編集後にblog/a/items/bにPUTします。
管理画面ではapp/views/layouts/admin/admin.html.erbというテンプレートを共通で使います。上部と左にメニューを表示します。実際にはコンテキストを見てハイライトする部分を変えるといった処理が必要ですが,今は固定的にメニューを表示しているだけです。
各管理画面のテンプレートはapp/views/adminの下にコントローラごとにディレクトリがあり,その中に入っています。現状はitemsのnew(新規アイテム追加)など一部しか作っていません。
管理画面を作っていくには,RESTfulの考えを理解している必要があります。Foodynの構成において重要な部分なので,これも項を改めて解説します。
ディレクトリ構成
以下ではFoodynをいじる人が必要になりそうな部分を説明します。
libのnc_parserがスキンやテンプレートを解釈実行する部分です。parse_xxxといったメソッド名はNucleusを踏襲しています。このディレクトリの中ではbase.rbが汎用のパーサー用メソッドなどを持つベース部分で他のクラスはこれを継承します。なお,Railsの命名規約に合わせて,nc_parserのbase.rbには「NCParser」モジュールの「Base」クラス,すなわち「NCParser::Base」を定義しています。こうしておくことで,アプリ内の他の部分からNCParser::Baseが呼び出されたときに,そのクラスが事前にロードされていなくても,Railsが必要なファイルを見つけてくれます。requireなどを書かずに利用できるわけです。
default_skin_parserはスキンタイプ共通のメソッドを集めており,スキンタイプごとのパーサーは,その子クラスになります。このほかテンプレート,テンプレート・コメント,アイテムをパース実行するクラスがあります。
なお,ここにskinsというサブディレクトリがありますが,使用予定はありません。無視してください。
app/modelsにデータを操作する部分がまとまっています。RailsにおけるMVCのM(モデル)であり,データベースのテーブル一つが一つのクラスに相当します。Railsではクラス名からテーブル名も自動的に決められて設定なしにアクセスできるのですが,テーブル接頭辞とテーブル名の語幹部分の設定を両立できないため,Foodynではテーブル名をモデルごとに明記する必要があります。例えばitem.rbでは「set_base_name :item」という記述が先頭のほうにあります。これでitemテーブルにアクセスします。接頭辞部分はconfig/database.yml内に記述するようにしています。productionとdevelopmentで接頭辞を変えたいといったことに簡単に対処するためです。
また,Railsではテーブル内のidという名称のフィールドをプライマリ・キーとして使用します。プライマリ・キーがないテーブルは書き込みできないなど使用に大きな制限が出るため,FoodynではNucleusが単独フィールドのプライマリ・キーを設けていないテーブルにもidフィールドを加えています。またitemテーブルのinumberなど,id以外の名称のプライマリ・キーがある場合は「set_primary_key :inumber」という指定をします。
モデルによっては内部に多くのロジックを持っています。代表的なのがitem.rb。クラスメソッドのget_listはアイテム一覧を得るための汎用的なメソッド。ページ名や1ページのアイテム数,カテゴリーやタグなどに対応しており,呼び出す側が拡張できるようにもなっています。例えば:orderを指定することでアルファベット順にリストを得るといったこともできます。インスタンス・メソッドのhas_rightは現在のユーザーが特定の権限を持っているかどうかを調べるメソッド。管理画面作成時などに必要になります。
blog.rbとmember.rbの中にもhas_rightというメソッドがあります。管理画面ではmemberに対してhas_rightで権限があるかどうかを調べます。そうするとblogやitemなどに対して権限を調べてもらうためにそれらのhas_rightが呼び出されます。
管理画面に関連するのはviewsのところですが,これについては項を改めて説明します。
なお,sample_database.ymlファイルをリネームすると,subversionのリポジトリ上のファイルも変えてしまう恐れがあるのでご注意ください。
Foodynのディレクトリに行き,
rake db:migrate
を実行します。これでFoodyn用にデータを書き換えます。エラーが出た場合はおそらくFoodynのバグなので,報告をお願いします。なお,Nucleusのデータは不要な部分も消去しないので,後ほど不要な部分は消して使うことをお勧めします。
もう一つ作業を忘れていました。スキンのデータ(例えば画像ファイルやCSS,parsedincludeで読み込むファイル)はDBには入っていないので,ファイルベースで移行する必要があります。Foodynのpublicというディレクトリの下にskinというディレクトリがあります。ここにNucleusのスキンディレクトリをそのままコピーしておきます。
次にサーバーを動かします。僕はAptanaの上から直接動かしています。例えばポート3000でサーバーを起動したら
http://localhost:3000/
にアクセスするとデフォルト・ブログを表示するはずです。サブブログは
http://localhost:3000/ブログのshortname
でアクセスできます。
管理画面は
http://localhost:3000/admin
です。
MySQLは4.x以降で文字コード関係のいやらしいところがいろいろありますが,FoodynではphpMyAdminで文字化けしている場合は,ちゃんと扱えません。Nucleusではそのあたりごまかしが効いてしまう部分もあり,文字化け状態のまま運用している人もいると思いますが,注意が必要です。もし,phpMyAdminで文字化けしているなら,NucleusでNP_DBCopyプラグインを使って,データベースをコピーし,config.phpを編集して,そちらのデータベースに切り替えてみてください。たぶんそれで文字化けしないDBに変えられると思います。Nucleusの上で,そこまでやっておく必要があります。
次にFoodyn用のデータを取り出す作業ですが,phpMyAdminのExport機能でもたぶん大丈夫なのですが,私はNP_BackupNeoでバックアップしたものを使っています。こちらの方が文字化けしないように思います。ただし,ときどきインポートできないデータを作ることがあるので,それらはエディタで編集して取っておきます。
Foodyn用のデータベースを作るときは,照合順序でutf8-...というのを選んでください。そうでないとやはり文字化けします。データベースを作ってデータをインポートすれば準備は終わりです。phpMyAdminで文字化けしていないことを確認してください。
なお,phpMyAdminが使えない,あるいはPHPを用意するのが面倒であれば,MySQL AdministratorというMySQLが公開しているGUIのツールでデータを移行することもできます(ダウンロードはこちら)。この場合,文字コード関係の設定はさらにシビアになるので,元環境がちゃんと設定されている必要があります。
Railsの環境作りについては,プラットフォーム依存の部分が多いので省略しますが,Rubyは1.8.x,Railsは2.1.0(現状の最新版)を入れてください。
Railsが使える統合開発環境はいくつかありますが,とりあえず自分が使っているという理由だけでAptana Studio(+RadRails)をお勧めします。Eclipseベースの環境でありJavaの上で動くので,クロス・プラットフォームで利用できます。Subversionのリポジトリと直接やり取りするSubsclipseというプラグインも利用できます。ただ,自分の環境(Windows)ではTortoiseSVNでSubversionをいじるとSubsclipseでバージョンが古いとして扱えなくなってしまいました。そこで,今はTortoiseSVNだけに絞っています。
Railsのアプリを置くためのディレクトリを作り(そこをAptanaでワークスペースとして登録します),そこにFoodynを入れるディレクトリを作ります。Foodynのディレクトリにsourceforge.netからFoodyn CMSのtrunkをcheckoutして来ます。URLは
https://foodyncms.svn.sourceforge.net/svnroot/foodyncms/trunk
となります。次にデータの準備方法を説明します。
Powered by Foodynの方のページはまだ,アイテムの追加などがちゃんとテストできていないので,データが古いままですが,上記のクエリーには対応しています。
タグを複数選んだときのANDやORの処理も行っており,今はテンプレートを調整していないのでリンクがありませんが,手作業でURLを入れれば動きます。
ANDの例
ORの例
このあたりは現在のNucleusよりも大分高速に動いていると思います。
次に何をやる予定だったのかも忘れてしまいましたが,とにかく合宿までにドキュメントを整備しないと。大変だ。
RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]
を.htaccessに入れると動くのですが,CGI版でもそれでいいかとやってみると動かないのです。FastCGIだとプログラム修正時にプロセスを殺さないといけないなど,面倒なので,当面はCGIで動かそうと思っていたのですが,目論見どおりにはいかないものです。しょうがないので今はFCGIにしています。
そんなバグ取りをしながら,デフォルト・テンプレートの機能だけは投入しました。おかげでテンプレートの修正なしにタグの表示ができて楽チンです。
ページスイッチは,NucleusだとShowBlogsが生成するものをそのまま使っている人が多いと思いますが,ここのページにあるようないろいろなデザインができないのが残念なところ。また,配置もアイテム表示の直前か直後に固定されてしまいます。
ページスイッチを表示するスキン変数を別途用意すればいいのですが,表示内容の指定などをblog変数に合わせないといけません。そこで,Foodynではデータセットという概念を導入して,二重指定を不要にしようと思っています。ページスイッチのスキン変数かblog変数かどちらか先に指定したものの表示内容(1ページに表示するアイテムの数など)をデータセットとして,他方はデータの指示なしに表示できるようにします。表示機能なしで,データセットの指定だけするスキン変数も用意します。
頭の中では,この機能を応用して,1ページ内に複数のページスイッチを別の用途で置けるようにする実装もできているのですが,ちょっと面倒な点がいくつかあるので,後でやることになると思います。
なお,テンプレートのデフォルト値やインライン・テンプレートのアイディアはページスイッチのスキン変数を考える際に思いついたもの。脈絡ないようですが,実はあるのです。
Foodynでは二つの新しい機能を使ってこの部分を少し使いやすいものにしようと考えています。一つはデフォルト機能。「conifg/default_template.yml」というYAMLのファイルを用意し,それに各テンプレート・パーツのデフォルト値を置けるようにします。これによって,テンプレート指定なしでも,全く表示がないといったことがなくなります。
もう一つはインライン・テンプレートの機能。どちらかというとプラグインなどからの利用を想定していますが,YAMLの表記ルール(あるいはJSON)を使って,ユーザーが利用できるようにすることもあり得るでしょう。これはデータベースにテンプレートを入れなくてもテンプレート機能を使えるようにするもの。例えばプラグインからパラメータによって,テンプレートを変えて出力するといった使い方が簡単にできるようになります。ユーザーレベルではスキンにこれを記述できるようにすると,テンプレートなしで書けるようになります。そちらは実装するかどうか未定。
ついでにこのサーバーでも動かそうとしているのですが
Application error
Rails application failed to start properly"
というエラーが出てしまい,うまく行きません。サーバーのエラーログも見ているのですが,理由がよく分かりません。困った困った。
Subversionでダウンロードおよびブラウズができます。
サンプルで付けているデータベース接続用ファイルがsqlite3になっていたり(修正済み),このままでは使い方が分からないと思うので,ドキュメント作ります。
とりあえず最低限のことを。
Windowsの方はXAMPP使うよりInstantRails入れるのが吉だと思います。PHPも動くし。僕はそれにRadRails入れて使ってます。CPUが遅いとつらいかもしれないけど,いろいろ楽なのは確かです。
Macでの環境構築はこちらが参考になるでしょう。
それとDB接続の設定をしてrake db:migrateすれば一応動くようになります。
それから念のため,今のところNucleusのDBがあることを前提にしています。なくても動きますが,管理画面がほとんどできていないので自分でレコード作らないといけないから。Nucleusのデータを使う場合,佐藤(な)さんのDBCopyプラグインを使うのがお勧めです。
インライン・テンプレート
インライン・テンプレートの機能,動くようになったのですが,今の「ネストなしパーサー」だとインラインでテンプレート書くときに<%%>が使えないので<::>に書きなおす必要があります。やはりこれだと面倒なので,ネスト付きパーサーに切り替えることを画策中です。
ただ,単純に切り替えただけではさすがにエラーが…。ちゃんとテストしていないメソッドなので当然ですが。しばらくバグ取りに時間がかかりそうです。
それと,このネスト付きパーサーを考えたときは,ネストの内側も全部解釈実行することを前提にしていたのですが,考えてみたら内側は別のパーサー(例えばスキン変数の内側はテンプレートのパーサーが扱うべき)で実行するのが普通なので,そのあたりの処理も変えないといけません。例えばifの解釈もネストできるのですが,そこはオーバースペックでしょう。
Foodynの各機能(仕様)への評価
先日のNucleusの合宿で行ったプレゼンについて,参加者にアンケートを取りました。全部紹介すると大変なので,各機能に付いての評価をまとめたものを図二つにしました。

おおむね好評だったといっていいと思うのですが,Ruby on Railsを使っていることについてはやはり賛否両論分かれました。実績が少ないことでの不安に加え,現在のところホスティングで使えるところが限られてしまうのが理由だと思います。
ただ,PHPやMySQLも5,6年前には安くて使えるところはほとんどありませんでした。Nucleusの最初のバージョンがでてきたころはPHPが広がった時期とほぼ同じではないかと思います。
Railsも後1年くらいでそれくらいのところまで来るのではないかというのが僕の予想です。
ほかにはHTTPの認証について,やはり意見が分かれました。ここも仕方ないところだと思いますが,Foodynではプラグインで別の認証が使えるようにしておく(はず)なので,大きな問題にはならないのではないかと思っています。
限られた時間でのプレゼンだったので,RESTにまつわるところなど説明が足りていない部分もかなりあると思いますが,それでもこれだけ理解してもらったことはありがたいことです。
OpenIDとブログ
FoodynではOpenID対応はプラグインで実現することになると思いますが(~~認証も),この手のログイン用にデフォルトで用意しているユーザーを増やさないといけないなあと思っています。すなわち,これまでだったらログインしている人はすべてメンバーだったわけですが,OpenIDなどが入ると,ログインしているけどゲストって状態があるわけで,ログインしていないゲストと別のロールにしておかないといけません。昨日書いたsafeスキンのフィールドも含めてちょっとテーブルをいじらないと。
テーブルいじること自体はMigration書くだけなので簡単なのですが,Migrationがあんまり多いと配布するときは格好悪いので,どこかでマージして数を減らす必要があります。そうすると既にインストールしている人にテーブルをいじってもらわないといけなくなるなど,また別の面倒が出てくるのが鬱陶しいところ。
複数スキン・エンジンのサンプル
先日のプレゼンについてのアンケート結果は近日まとめるつもりですが,なかで「複数表示エンジン」のところが具体例がないとちょっと分かりにくいかなという話があり。そこで考えてみたのですが,一番簡単で,かつ意味があるサンプルとして,次のようなエンジンを考えてみました。先日のプレゼンでは時間の関係でさらっとしか話しませんでしたが,Foodynではスキン・エンジンに「safe」あるいは「unsafe」の属性が付きます。デフォルトのNucleus互換エンジンは「unsafe」なので,「safe」なスキンしか使えないユーザーはアクセスできません。そこで,Nucleus互換のエンジンを使った「safe」なエンジンが必要になります。
このエンジンでは,ユーザーはスキンの選択はできますが編集できません。indexページに表示するアイテムの数だけが設定できます。
この程度のエンジンだったら簡単に作れますし,イメージつきやすいかなあと。
インライン・テンプレートとヘッダー変数を実装
仕様として書いたからには実装しないと,ということでNucleus互換表示エンジンにヘッダー・スキン変数の機能とインライン・テンプレートの機能を実装しました。ヘッダーの方はごくごく簡単で,コントローラにヘッダを保持するハッシュを用意しておき,プラグインから読み書きできるようにして,スキン変数で書き出すだけです。文字列でなくハッシュにしたのは,同じものが既にないかどうか調べられるようにするため。インライン・テンプレートはスキン変数のパラメータに{}で挟まれた部分があると,そこをJSON(実際にはYAMLのライブラリを使っていますが)として解釈するもの。まだちゃんとデバッグはしていませんが,たぶんそんなに問題はないでしょう。
Nucleusの開発合宿に参加しました
Nucleusの開発合宿に行ってきました(詳しくはこちら)。とはいえ二泊三日のうち中日の日帰りという一部の参加でした。Foodyn CMSについてはこのブログにいろいろ書いてはいますが,見ていない人も多いだろうし,情報がまとまっていないので,この機会にどういうものだか理解してもらおうと,時間を取ってもらってプレゼンさせてもらいました。前の記事のプレゼンはそのための資料です。
午前中に1回と,見逃した人用に夕食後に1回,計1時間近く使わせていただきました。ありがとうございました。これが何かのきっかけになればと思います(Sourceforge.netのDevelopersは一人増えました。^^)。
また,ページスイッチの部分を実装しました。一つのページの中に複数の切り替え用スイッチ(例えば一つはメインブログ,もう一つはサブブログの切り替え用)を置けます。実装は案外苦労しましたが,割と面白い機能になったかと思います。
トップ・ページとレイアウト機能に対応しました
サイト・トップにアクセスしたときに「main」スキンがあったら,そちらを表示する機能と,レイアウト機能,デフォルト・スキン・パートの機能を実装しました。これらを使うと最低限のスキンを作ることがこれまでよりかなり簡単になるだろうと思います。
インライン・テンプレートの機能を加えれば,スキン編集一つだけでも済ませられるようになります。
Foodynのプレゼンを作りました
フルスクリーンで見るにはこちら。管理画面とRESTful
Foodynは基本的にRESTfulなアーキテクチャを採用しています。それが特に顕著なのが管理画面です。RESTfulについてはyohei-y:weblogのREST入門やリコーの研究部門によるドキュメントが分かりやすくまとまっています。またRailsにおける実装についてはRuby on Rails勉強会で翻訳したものが簡潔にまとまっています。
ここではさらに簡単に言うとRESTはリソースをURLで表現し(例えばhttp://example.com/blog/a/item/b でブログaのアイテムbをあらわす),HTTPのverb(GET,POST,PUT,DELETE)でそれに対する操作を決めます。例えば,前述のURLをGETするとブログaのアイテムbを表示し,PUTすると内容を更新し,DELETEすると削除します。実際にはPUTとDELETEは現在のWebブラウザがサポートしていないので,RailsではPOSTとhiddenなフィールドを使って擬似的に実現しています。前述の勉強会の記事ではRESTの操作とRailsで呼び出されるコントローラのメソッドの関係が記述されています。
RESTを使うメリットとしてはリソースと操作が分離されて分かりやすくなること,副作用が伴う操作でGETを使うことはないこと,「ステート」がないためスケールしやすいこと,があります。RESTではHTTPのプロトコルですべてが表現されるというのが基本なのでクッキーも使いません。認証はBASIC認証やDIGEST認証といったHTTP標準でブラウザがサポートしているものを使います。
具体例で示します。Foodynの管理画面では,最初に開いたときにblogのindexを表示します。そこからブログaのアイテム一覧を表示するのはblog/a/itemsというリソース(itemが複数形になっていることに注意)をGETすることです。ブログaに新規アイテムを作るには最初にblog/a/items/newをGETして新規入力用フォームを表示します。入力後blog/a/itemsにPOSTすることにより,新しいアイテムができます。また,ブログaのアイテムbを編集するにはblog/a/items/b/editをGETして,編集後にblog/a/items/bにPUTします。
管理画面の構成
管理画面はレイアウト機能を利用します。レイアウト機能とはメニュー部分など,様々な画面で使いまわす部分をレイアウトとして独立させたもの。Railsではapp/views/layouts/の中に入っています。モデルをRailsのscaffold機能で生成させたりすると,自動的にレイアウトも作られるので,注意が必要です。Foodynにはその名残のファイルも入っていますが実際には使用していません。管理画面ではapp/views/layouts/admin/admin.html.erbというテンプレートを共通で使います。上部と左にメニューを表示します。実際にはコンテキストを見てハイライトする部分を変えるといった処理が必要ですが,今は固定的にメニューを表示しているだけです。
各管理画面のテンプレートはapp/views/adminの下にコントローラごとにディレクトリがあり,その中に入っています。現状はitemsのnew(新規アイテム追加)など一部しか作っていません。
管理画面を作っていくには,RESTfulの考えを理解している必要があります。Foodynの構成において重要な部分なので,これも項を改めて解説します。
Foodynのディレクトリ構成
Foodynの現状のディレクトリ構成を表にまとめました。Railsが標準で作成するディレクトリとFoodynが独自に作っている部分が分かるように,Railsによるディレクトリは黄色で示しています。ディレクトリ構成
以下ではFoodynをいじる人が必要になりそうな部分を説明します。
libのnc_parserがスキンやテンプレートを解釈実行する部分です。parse_xxxといったメソッド名はNucleusを踏襲しています。このディレクトリの中ではbase.rbが汎用のパーサー用メソッドなどを持つベース部分で他のクラスはこれを継承します。なお,Railsの命名規約に合わせて,nc_parserのbase.rbには「NCParser」モジュールの「Base」クラス,すなわち「NCParser::Base」を定義しています。こうしておくことで,アプリ内の他の部分からNCParser::Baseが呼び出されたときに,そのクラスが事前にロードされていなくても,Railsが必要なファイルを見つけてくれます。requireなどを書かずに利用できるわけです。
default_skin_parserはスキンタイプ共通のメソッドを集めており,スキンタイプごとのパーサーは,その子クラスになります。このほかテンプレート,テンプレート・コメント,アイテムをパース実行するクラスがあります。
なお,ここにskinsというサブディレクトリがありますが,使用予定はありません。無視してください。
app/modelsにデータを操作する部分がまとまっています。RailsにおけるMVCのM(モデル)であり,データベースのテーブル一つが一つのクラスに相当します。Railsではクラス名からテーブル名も自動的に決められて設定なしにアクセスできるのですが,テーブル接頭辞とテーブル名の語幹部分の設定を両立できないため,Foodynではテーブル名をモデルごとに明記する必要があります。例えばitem.rbでは「set_base_name :item」という記述が先頭のほうにあります。これでitemテーブルにアクセスします。接頭辞部分はconfig/database.yml内に記述するようにしています。productionとdevelopmentで接頭辞を変えたいといったことに簡単に対処するためです。
また,Railsではテーブル内のidという名称のフィールドをプライマリ・キーとして使用します。プライマリ・キーがないテーブルは書き込みできないなど使用に大きな制限が出るため,FoodynではNucleusが単独フィールドのプライマリ・キーを設けていないテーブルにもidフィールドを加えています。またitemテーブルのinumberなど,id以外の名称のプライマリ・キーがある場合は「set_primary_key :inumber」という指定をします。
モデルによっては内部に多くのロジックを持っています。代表的なのがitem.rb。クラスメソッドのget_listはアイテム一覧を得るための汎用的なメソッド。ページ名や1ページのアイテム数,カテゴリーやタグなどに対応しており,呼び出す側が拡張できるようにもなっています。例えば:orderを指定することでアルファベット順にリストを得るといったこともできます。インスタンス・メソッドのhas_rightは現在のユーザーが特定の権限を持っているかどうかを調べるメソッド。管理画面作成時などに必要になります。
blog.rbとmember.rbの中にもhas_rightというメソッドがあります。管理画面ではmemberに対してhas_rightで権限があるかどうかを調べます。そうするとblogやitemなどに対して権限を調べてもらうためにそれらのhas_rightが呼び出されます。
管理画面に関連するのはviewsのところですが,これについては項を改めて説明します。
Foodynの利用方法――③Foodynを動かす
データをMySQLに入れたら,いよいよFoodynを動かす準備に入ります。まず,configディレクトリにdatabase.ymlというファイルを作ります。sample_database.ymlというファイルからdatabase.ymlに内容をコピーし,データベースの名前など,必要な設定を記入します。MySQLのデータベース・テーブルに付ける接頭辞もここで指定します(デフォルトは互換性のためにnucleusになっています)。なお,sample_database.ymlファイルをリネームすると,subversionのリポジトリ上のファイルも変えてしまう恐れがあるのでご注意ください。
Foodynのディレクトリに行き,
rake db:migrate
を実行します。これでFoodyn用にデータを書き換えます。エラーが出た場合はおそらくFoodynのバグなので,報告をお願いします。なお,Nucleusのデータは不要な部分も消去しないので,後ほど不要な部分は消して使うことをお勧めします。
もう一つ作業を忘れていました。スキンのデータ(例えば画像ファイルやCSS,parsedincludeで読み込むファイル)はDBには入っていないので,ファイルベースで移行する必要があります。Foodynのpublicというディレクトリの下にskinというディレクトリがあります。ここにNucleusのスキンディレクトリをそのままコピーしておきます。
次にサーバーを動かします。僕はAptanaの上から直接動かしています。例えばポート3000でサーバーを起動したら
http://localhost:3000/
にアクセスするとデフォルト・ブログを表示するはずです。サブブログは
http://localhost:3000/ブログのshortname
でアクセスできます。
管理画面は
http://localhost:3000/admin
です。
Foodynの利用方法――②データの準備
FoodynではUTF-8のデータだけが利用できます。データベースはMySQL以外でも動く可能性はありますが,一応現状はMySQLだけをサポートしています。SQLiteはタグ/カテゴリーで使っているクエリーの機能で対応していないところがあったと思います。MySQLは4.x以降で文字コード関係のいやらしいところがいろいろありますが,FoodynではphpMyAdminで文字化けしている場合は,ちゃんと扱えません。Nucleusではそのあたりごまかしが効いてしまう部分もあり,文字化け状態のまま運用している人もいると思いますが,注意が必要です。もし,phpMyAdminで文字化けしているなら,NucleusでNP_DBCopyプラグインを使って,データベースをコピーし,config.phpを編集して,そちらのデータベースに切り替えてみてください。たぶんそれで文字化けしないDBに変えられると思います。Nucleusの上で,そこまでやっておく必要があります。
次にFoodyn用のデータを取り出す作業ですが,phpMyAdminのExport機能でもたぶん大丈夫なのですが,私はNP_BackupNeoでバックアップしたものを使っています。こちらの方が文字化けしないように思います。ただし,ときどきインポートできないデータを作ることがあるので,それらはエディタで編集して取っておきます。
Foodyn用のデータベースを作るときは,照合順序でutf8-...というのを選んでください。そうでないとやはり文字化けします。データベースを作ってデータをインポートすれば準備は終わりです。phpMyAdminで文字化けしていないことを確認してください。
なお,phpMyAdminが使えない,あるいはPHPを用意するのが面倒であれば,MySQL AdministratorというMySQLが公開しているGUIのツールでデータを移行することもできます(ダウンロードはこちら)。この場合,文字コード関係の設定はさらにシビアになるので,元環境がちゃんと設定されている必要があります。
Foodynの利用方法――①Subversionでチェックアウト
現状は管理画面で設定できることが限られているので,Nucleusからのデータ移行のテストとして考えてください。Railsの環境作りについては,プラットフォーム依存の部分が多いので省略しますが,Rubyは1.8.x,Railsは2.1.0(現状の最新版)を入れてください。
Railsが使える統合開発環境はいくつかありますが,とりあえず自分が使っているという理由だけでAptana Studio(+RadRails)をお勧めします。Eclipseベースの環境でありJavaの上で動くので,クロス・プラットフォームで利用できます。Subversionのリポジトリと直接やり取りするSubsclipseというプラグインも利用できます。ただ,自分の環境(Windows)ではTortoiseSVNでSubversionをいじるとSubsclipseでバージョンが古いとして扱えなくなってしまいました。そこで,今はTortoiseSVNだけに絞っています。
Railsのアプリを置くためのディレクトリを作り(そこをAptanaでワークスペースとして登録します),そこにFoodynを入れるディレクトリを作ります。Foodynのディレクトリにsourceforge.netからFoodyn CMSのtrunkをcheckoutして来ます。URLは
https://foodyncms.svn.sourceforge.net/svnroot/foodyncms/trunk
となります。次にデータの準備方法を説明します。
カテゴリーとタグのクエリーに対応
階層カテゴリーやタグを選んだときに,ちゃんと表示するよう,クエリー部分を全面的に書き換えました。パラメータを全部ハッシュで受けるようにして,柔軟性,拡張性もこれまでより大分ましになりました。まだユーザー権限の処理が入っていないのですが,とりあえず大分使い物にはなります。Powered by Foodynの方のページはまだ,アイテムの追加などがちゃんとテストできていないので,データが古いままですが,上記のクエリーには対応しています。
タグを複数選んだときのANDやORの処理も行っており,今はテンプレートを調整していないのでリンクがありませんが,手作業でURLを入れれば動きます。
ANDの例
ORの例
このあたりは現在のNucleusよりも大分高速に動いていると思います。
バグ取りにいそしむ
カテゴリーの移行時にうまくいかないときがあることがわかり,そのバグを取るのにずいぶん時間を使ってしまいました。次に何をやる予定だったのかも忘れてしまいましたが,とにかく合宿までにドキュメントを整備しないと。大変だ。
デフォルト・テンプレートを実装
実際にホスティングのサーバー上で動かしてみるとやはりローカルのテストでは出てこなかったバグが表面化するもので,調整に追われています。中でも苦労しているのが認証関係で,標準の状態ではApacheがRailsにHTTP認証関係のヘッダを渡してくれないため,認証が失敗してしまいます。いろいろ調べるとFastCGIを使うときはRuby on Rails/apache2+FastCGIでBASIC認証という記事にあるようにRewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]
を.htaccessに入れると動くのですが,CGI版でもそれでいいかとやってみると動かないのです。FastCGIだとプログラム修正時にプロセスを殺さないといけないなど,面倒なので,当面はCGIで動かそうと思っていたのですが,目論見どおりにはいかないものです。しょうがないので今はFCGIにしています。
そんなバグ取りをしながら,デフォルト・テンプレートの機能だけは投入しました。おかげでテンプレートの修正なしにタグの表示ができて楽チンです。
ページスイッチ部分の仕様
Foodynの公開をしてから,そういえばカテゴリー部分のクエリーを実装していなかったことに気付き,作業中です。それだけならたいした手間ではないのですが,以前から頭のどこかにあったページスイッチ部分を実装しようかと思い,遠回り中です。ページスイッチは,NucleusだとShowBlogsが生成するものをそのまま使っている人が多いと思いますが,ここのページにあるようないろいろなデザインができないのが残念なところ。また,配置もアイテム表示の直前か直後に固定されてしまいます。
ページスイッチを表示するスキン変数を別途用意すればいいのですが,表示内容の指定などをblog変数に合わせないといけません。そこで,Foodynではデータセットという概念を導入して,二重指定を不要にしようと思っています。ページスイッチのスキン変数かblog変数かどちらか先に指定したものの表示内容(1ページに表示するアイテムの数など)をデータセットとして,他方はデータの指示なしに表示できるようにします。表示機能なしで,データセットの指定だけするスキン変数も用意します。
頭の中では,この機能を応用して,1ページ内に複数のページスイッチを別の用途で置けるようにする実装もできているのですが,ちょっと面倒な点がいくつかあるので,後でやることになると思います。
なお,テンプレートのデフォルト値やインライン・テンプレートのアイディアはページスイッチのスキン変数を考える際に思いついたもの。脈絡ないようですが,実はあるのです。
テンプレート機能を使いやすくする
Nucleusの柔軟性を高めているのと同時に分かりにくいと言われる原因でもあるのがテンプレートのところだと思います。一つのテンプレートの中にも,アイテム表示に関連する部分,カテゴリーリストに関連する部分,コメントに関連する部分,画像表示に関連する部分など,いろいろな部分があることがさらに分かりにくさに拍車をかけています。Foodynでは二つの新しい機能を使ってこの部分を少し使いやすいものにしようと考えています。一つはデフォルト機能。「conifg/default_template.yml」というYAMLのファイルを用意し,それに各テンプレート・パーツのデフォルト値を置けるようにします。これによって,テンプレート指定なしでも,全く表示がないといったことがなくなります。
もう一つはインライン・テンプレートの機能。どちらかというとプラグインなどからの利用を想定していますが,YAMLの表記ルール(あるいはJSON)を使って,ユーザーが利用できるようにすることもあり得るでしょう。これはデータベースにテンプレートを入れなくてもテンプレート機能を使えるようにするもの。例えばプラグインからパラメータによって,テンプレートを変えて出力するといった使い方が簡単にできるようになります。ユーザーレベルではスキンにこれを記述できるようにすると,テンプレートなしで書けるようになります。そちらは実装するかどうか未定。
Rails2.1対応
Rails2.1に対応しようとしたら,ちょっとトラブリましたが,今は無事に動いています。Sourceforgeの方も修正済みなので,Rails2.1で動くはずです。ついでにこのサーバーでも動かそうとしているのですが
Application error
Rails application failed to start properly"
というエラーが出てしまい,うまく行きません。サーバーのエラーログも見ているのですが,理由がよく分かりません。困った困った。
一応公開しました
Sourceforgeのページはこちら。Subversionでダウンロードおよびブラウズができます。
サンプルで付けているデータベース接続用ファイルがsqlite3になっていたり(修正済み),このままでは使い方が分からないと思うので,ドキュメント作ります。
とりあえず最低限のことを。
Windowsの方はXAMPP使うよりInstantRails入れるのが吉だと思います。PHPも動くし。僕はそれにRadRails入れて使ってます。CPUが遅いとつらいかもしれないけど,いろいろ楽なのは確かです。
Macでの環境構築はこちらが参考になるでしょう。
それとDB接続の設定をしてrake db:migrateすれば一応動くようになります。
それから念のため,今のところNucleusのDBがあることを前提にしています。なくても動きますが,管理画面がほとんどできていないので自分でレコード作らないといけないから。Nucleusのデータを使う場合,佐藤(な)さんのDBCopyプラグインを使うのがお勧めです。