Categories
open all | close allTags
アクセス制御 | Aptana | 国際化 | 認証 | スキンエンジン | rake | タグ | ドキュメント | CSRF | Subversion | OpenID | テスト | モデル | Flash | パソコン | 名称 | デュアル・コア | Migration | フォーム | RESTfulSearch
テスト
プラグインの動作関係をちゃんとテストを書いて検証しようと思っているのですが,これまで手動テストばかりやっていたので,テストの書き方を全く覚えていません(泣)。この機会にちゃんとしたいところ。プラグインの雛形もgeneratorで生成できるようにしたいのですが,ちょっと面倒なので,もっと仕様が落ち着いてから手を付けることになりそうです。
migrationでインデクスを生成させていたら,「名前が長すぎる」というエラーが。インデクスに使うカラム名を名前に入れていくので,カラムが複数とかになるとすぐに長くなってしまいます。とりあえずテーブル名などを短くすることで対処しましたが,名前設定てできるのかな?
RESTful Webサービス
オライリーから出ている「RESTful Webサービス」を読みました。現在のところRESTfulなアプリケーションの作り方について,まとめられているものとしては一番詳しいと思います。タイトルにあるように,主体はWebサービスの設計。FoodynのようなWebアプリケーションについての記載はあまり多くはありません。それでも,これまで考えてきたことを改めて整理したり,RESTfulな考え方をなじませるためにはかなり役に立ったような気がします。例えば,トランザクション処理は,これまでステートレスであるRESTfulにはなじまないものと思い込んでいましたが,トランザクション自体をリソースとして処理する方法が挙げられており,これには目から鱗が落ちる思いがしました。
例として挙げられているコードはほとんどがRuby on Railsなので,読者もRubyとRailsが分かることがある程度要求されそうです。Ruby知らなくても概ね雰囲気はつかめると思いますが。
RESTfulなWebサービスやアプリケーションを開発する人にとっては一度は読むべきものだと思います。
RESTful Webサービス
Leonard Richardson、Sam Ruby、山本 陽平、株式会社クイープ
オライリー・ジャパン
2007/12/21
¥ 3,990 (定価)
¥ 3,990 (Amazon価格)
39pt (Amazonポイント)
(私のおすすめ度)
★★★ (Amazonおすすめ度)
単行本
通常24時間以内に発送
(価格・在庫状況は10月11日 20:33現在)
Leonard Richardson、Sam Ruby、山本 陽平、株式会社クイープ
オライリー・ジャパン
2007/12/21
¥ 3,990 (定価)
¥ 3,990 (Amazon価格)
39pt (Amazonポイント)
(私のおすすめ度)
★★★ (Amazonおすすめ度)
単行本
通常24時間以内に発送
(価格・在庫状況は10月11日 20:33現在)
うまくいった
ライブラリを呼び出すための$LOAD_PATHに対してクラス名+migrationのディレクトリがあるかどうかを調べていくことで問題解決(多分)。コードはこんな感じ。
def schema_version
match = Regexp.new('^(\d{3,})_(.*)\.rb$')
max = 0
$LOAD_PATH.each do |load_path|
path = load_path + '/' + name.underscore + '/migration'
begin
Dir.foreach(path) do |fname|
if fname =~ match
version = $1.to_i
max = version if version > max
end
end
return max
rescue
end
end
return 0
end行き詰まり
プラグイン関係の実装を粛々と行っているのですが,困ったことが1つあって停滞中。前に書いたように,Railsのマイグレーションに相当する機能をプラグインに対して実現しようとしています。ここでマイグレーションのファイルを調べにいこうとしているのですが,ディレクトリを自動的に検知してファイルを走査するところがうまくいきません。プラグインのクラスがあるファイルに対して相対的なディレクトリを示す方法が見つかっていないからです。プラグインの親クラスで定義すると,親クラスのあるディレクトリに対して実行してしまいます。
マイグレーションのファイルを読み込ませてしまえばなんとかなるとは思うのですが,毎回読み込むのは無駄ですし。うーん,困った。
解決:プラグインからDBのテーブルを作る方法
見つけました。というか独自にテーブルが必要そうなプラグインをインストールして,どうやっているかを見てみました。とりあえず以下のコードで動くことを確認。
class TestDB
def createtable
ActiveRecord::Schema.create_table('test') do |t|
t.column :str, :string
end
end
endこれをlibディレクトリにtest_db.rbとして保存し,コンソールを開いて a = TestDB.new と a.createtable を実行したらテーブルができました。実際にはテーブルの存在チェックなどが必要ですが,ともかくこれでプラグイン内でテーブルが作れることが分かりました。
ActiveRecord::Schemaのドキュメントを見ると
ActiveRecord::Schema.define do
create_table :authors do |t|
t.string :name, :null => false
end
add_index :authors, :name, :unique
create_table :posts do |t|
t.integer :author_id, :null => false
t.string :subject
t.text :body
t.boolean :private, :default => false
end
add_index :posts, :author_id
endといった書き方ができるようです。
プラグイン・オプションも含めてプラグイン内マイグレーション機能を入れたら結構使いやすいのではないかといったことを考えています。
プラグインからDBを使うには?
プラグインのアーキテクチャを考える際に,どうしたらいいのかまだよく分かっていないところがあります。例えばプラグイン独自のテーブルを用意したい場合。Migrationを使ってテーブルを生成するのだとすると,db/migrationディレクトリにファイルを作らないといけません。つまりプラグインをインストールした後,script/generateでmigrationファイルを作るといった手順になります。act_as_authenticatedなどはこの方法を使っています。
ただ,プラグインと本体のテーブルは別々に管理したいといったことを考えるとプラグインのコード内でテーブルを作ったり削除したりする,Nucleusに近いスタイルの方が書きやすいかもしれません。このとき,プラグインのコードからcreate_tableなどを呼び出す方法がまだつかめていません。ActiveRecordの中のコードなので,呼び出し方はあるはずだと思うのですが。
検索しても,そういったイレギュラーなやり方は見つからないので,暗中模索といった感じです。
PS. やっぱり一筋縄では行きそうにありません。無謀っぽい。
Migrationをまじめに書く
このところ何をしていたかというと,スキン・エンジンの抽象化作業の残りを続けていました。具体的にはMigrationを書くところ。これまではNucleusのテーブルそのものしか使っていなかったので,実はMigrationを全然書いていなかったのですが,ここで新しいテーブルを導入するためにどうしても必要になったのです。
書いてみるとなかなか楽しい。Nucleusのアップグレードスクリプト相当のものが簡単にできてしまいます。
ちなみに,スキン・エンジンに関係するところは次のよう。
def self.up
create_table :skin_engines do |t|
t.string :klass_name
end
newengine = SkinEngines.new
newengine.klass_name = 'Skin'
newengine.save
create_table :skins do |t|
t.string :skin_name
t.integer :skin_engine
end
add_column :blog, :bskinid, :integer
engines = SkinEngines.find(:all)
blogs = Blog.find(:all)
engines.each do |engine|
engine.klass_name.constantize.find_skins.each do |skin|
s = Skins.new
s.skin_name = skin.name
s.skin_engine = engine.id
s.save
blogs.each do |b|
if b.oldskin.sdname == skin.name
b.bskinid = s.id
b.save
end
end
end
end
end
初めにスキン・エンジンのテーブルを作っていますが,ここは実際にパースを行うクラスをのフィールドだけというシンプルなものです。ついでにデフォルトのSkinクラスを最初のアイテムとして登録しています。
次のskinsのテーブルは抽象化されたスキンのクラス。つまり,いろいろなエンジンのスキンを一緒くたに登録するためのテーブルです。ここではスキンの名前とエンジンのIDのフィールドがあります。
次に,blogテーブルにbskinidというフィールドを加えています。これは今作った抽象化スキンのIDを入れるフィールドです。既にあるbdefskinフィールドを使ってもいいのですが,それだとNucleusとのテーブルの共存ができなくなるため,別フィールドを加えました。
次に,既にスキンの登録が各エンジンにある場合,これを新しいテーブルに登録していく作業をしています。ブログのデフォルトスキンを新しく作ったフィールドに加える作業もここでします。
Migrationは全部1つにまとめてしまうことも可能ですが,このように段階を追って作っておいたほうがメンテナンスは楽になりそうです。
スキン変えてみました
ロゴもどきを入れてみたかったからですが,本当はMultipleCategoriesとかTagEXも入れておきたいんですよねえ。データの移行をテストするのに使えるから。あ,そういえばCustomURL使っているとテンプレートもいじる必要あったのかな?
このあたりのデファクト・スタンダード的な機能は最初から入っていたほうが,スキン作る人にとっては楽だろうな,というのがFoodynに取り込む理由です。
それにしても仕事が忙しくてコーディングをする時間が全然ないのが困りもの。
ロゴ

もう一つ作ってみました。
とは言っても白州書体を並べただけですが。
Foodyn CMSとは
名称決定(ほんとかな?)を受けて,改めて(内輪向けでない)紹介を書いておきます。
Foodyn CMSとは
●基本仕様
・Ruby on Railsをプラットフォームとするブログ・ベースのCMSです。オープンソースで公開します(ライセンス未定)。
・PHPで実績があるNucleus CMSのデータとほぼ互換性を持ちます。
・複数言語をサポートします。
・Nucleusと同様,複数ユーザー,複数ブログの運用が可能です。
・画面表示をつかさどる「スキン」のシステムもNucleus CMSとほぼ互換性があります。
・Nucleusの特徴の一つである,豊富なプラグイン・サポート機能を用意します。
●アドバンス仕様
・Nucleusではプラグインで実現している,複数ブログをまとめた表示機能,ページスイッチ,ツリー型カテゴリー,タグ,自由な名前を使ったURLといった機能を標準で用意します。
・Nucleusよりもきめ細かな,ユーザー管理機能を持ちます。例えば記事を書く人とチェックをする人が別,といった運用ができます。
・「スキン」のエンジンは複数利用できます。また,ある「スキン」から別のスキン・エンジン用のスキンを生成して実行することもできます。スキンのアクセス権はエンジンごとに設定できるので,例えば「信頼できないユーザーにはスキンの選択と色の調整しかさせない」といったことが可能になります。
・入力画面ではWYSIWYGエディタを利用できます。
作者「Andy」について
・Ruby on Railsでの開発は初めて。Rubyもほぼ初めてに近いです。
・PHPではNucleus CMSのコア開発メンバーに入っているほか,mbstringエミュレータというPHPの漢字処理機能のエミュレータを開発。Nucleus日本語版など日本語の処理機能を持つプログラムがmbstringが入っていないサーバーでもほとんど無変更で動くようにした実績があります。これはPHPで書いた最初のプログラムでした。
・Foodyn CMSの開発を始めたのは,自分で仕様・実装を決めて作ってみたくなったこと,Railsが話題になっており,使ってみたかったこと,などが動機です。Nucleusが嫌になったわけではありません。
・普通のサラリーマンであり,エンジニアでもありません。開発は夜中にこつこつやっています。
というわけで開発協力者募集中です。連絡は webmaster アット matsubarafamily.com までお願いします。
