Categories
open all | close allTags
モデル | デュアル・コア | Flash | フォーム | JustPosted | スキンエンジン | Subversion | 国際化 | タグ | パソコン | ドキュメント | rake | Aptana | RESTful | 名称 | CSRF | 認証 | テスト | アクセス制御 | MigrationSearch
落ち穂拾い
Configテーブルで初期設定が必要なデータなど,一からインストールする場合に必要になる項目を調べて備えています。サイト名とURLはインストーラで設定するようにしました。インストーラ難しかった
実際に動かしてみると,難問にぶち当たりました。DBのテーブルがない状態ではWebが起動しないのです。いや実際には設定を変えれば起動できるのですが,これだと今度はマイグレーションを実行したりといったことができません。結局言語設定とサイトオーナー設定の部分だけになってしまいそうです。これだとあんまりメリットないけど,サイトオーナー設定はやらないと困るので一応この機能は生かしておきます。
インストーラの起動条件
インストーラは一応できたのですが,起動条件がまだちゃんと定まっていません。パスワードなしで動き,DBやメンバー追加などをしてしまうので,初期状態のとき以外は起動しないようにかなり気をつける必要があります。起動を許可する条件と,その条件をセットする方法およびタイミング,起動条件を解除する方法およびタイミング,条件が整わないときに起動させない方法の四つを決めないといけません。それからインストーラでどこまで設定させるかという問題もあります。当初はDBへの接続設定を入れるつもりだったのですが,DBの設定ファイルがないとRailsのアプリケーションが起動しません。ごまかして起動することは可能なのですが,設定ファイルの更新後に,元に戻す方法が難しい。単純にファイルを書き換えるだけではFastCGI環境のようにロードしたまま実行するものではうまくいきません。どこかで現在のプロセスを殺して再起動させないといけませんが,そこまでをインストーラに盛り込むのは不可能です。
別案として,インストーラ専用のアプリケーションを作り,そこから設定させるというのも考えたのですが,手間ばかりかかってしまい,インストーラが作業を軽減させてくれているのか分からなくなってしまいます。そこまでやるのなら,アプリケーション本体もインストーラがサーバーから持ってきてインストールするといったブラウザのインストールなどでよく見られる方法を取るのもありかなあとは思うのですが,今度はSubversionからデータを取ってくるという,新たな壁にぶつかります。svnコマンドを呼び出すことで,できそうな雰囲気もありますが,これは後の課題ということで。
さて,話を戻してインストーラの条件ですが,起動許可条件としては,特定のファイルが存在すること,DB内に必要なテーブルが存在していないこと,あるいは存在していて,テーブル内に特定のレコードがあること,を考えています。偶然に条件が整ってしまう可能性がほとんどない(ファイルあるいはレコードの存在を条件にしている),進入されて実行される可能性が低い(ファイルとDBの両方をクラックされてしまうとしたら,そもそもインストーラうんぬんとは関係なく侵入者はなんでもできてしまう)というのが理由です。
条件の設定方法は,まずファイルは初期コピー時に含まれます。DBのフィールドはマイグレーションで設定します。初期状態ではフィールドの代わりにテーブルがないことが条件として使われます。
これで起動するとマイグレーションを実行し,言語設定を行い,サイト・オーナー設定を行って完了です。終了時に,ファイルを消去し,DBのフィールドを削除して手続き完了です。
起動条件の判定は,一応インストーラのメイン・メソッド内に入れるつもりです。それがプロセスの再起動なしで一番簡単にできるので。
【追記】プラグインのインストールでSubversionを呼び出すところはsystem関数に"svn export ..."を実行させていた。
備忘メモ:ping送信管理部分の実装
未来の記事を投稿したときなどにもちゃんと公開時にpingを打ったり,mixiの日記を投稿したりするようにするための実装についてのメモ。専用のテーブルpingsにはフィールドとして,公開日時,アイテムのID,コールバックするプラグインのID,オプショナル・データ(プラグインが自由に使える)を持つ。
アイテムがパブリッシュされるときに,プラグインがreserve_pingメソッドを呼ぶと,このテーブルに予約される。その場でpingを発行するときも,必ずこのインタフェースを通す。
アイテムが公開状態になる(公開時刻に達する)と,このテーブルのデータを元にプラグインにevent_send_pingが送られ(非同期に実行できたりするとうれしいけど,それは難しいかな?),テーブルのデータは消去される。
アイテムがパブリッシュから別の状態に変わったときもテーブルのデータを消す。
これでプラグイン側は予約して受け取るというインタフェースを実装するだけで済むはず。
備忘メモ:アプリケーションからMigrationを実行するコード
Ruby on RailsのGoogleグループより
if (ActiveRecord::Migrator.new(:up, 'db/migrate').pending_migrations.length > 0)
ActiveRecord::Migration.verbose = false
ActiveRecord::Migrator.migrate("db/migrate/", nil)
end
うまく応用するとプラグインのマイグレーション部分にも使えるかも。
備忘メモ:公開最終日時とワークフロー
アイテム・テーブルに公開最終日時のフィールドを加え,期間限定アイテムを簡単に作れるようにします。ワークフローは現行のidraftフィールドをそのまま使うかな。0がパブリッシュ,1がペンディング,2がドラフト。カスタマイズはできないけど,ロールごとにパブリッシュできるかどうかの設定ができます。機能的には不十分かもしれませんが,とりあえず最低ラインの機能にはなるかと思います。
もっと拡張可能な形にすることも考えられますが,そうするとフローの設定なども管理画面でやらないといけなくなり,ロールごとの設定もかなり面倒なことになります。ちょっとやりすぎになりそうなので自重します。
【追記】「差し戻し」の状態も作ること。
備忘メモ:権限の名称
ロールの設定をするときに権限の名前をどうするか,あまり考えていませんでした。デフォルトで用意されている権限は,この権限ならこの名前と勝手に紐付けられますが,プラグインなどで追加した権限はどうするか。権限のテーブルに名前のフィールドを持たせればある程度解決しますが,国際化のところの対応がいまいち。プラグインに国際化テーブルを持たせて,起動時に読み込む? 読み込むのが増えると速度に影響しそうなのがちょっと心配です。かといって権限テーブルにプラグインの情報を持たせて呼びに行くというのもどうかなあ。頻繁に使う機能ではないので,それくらいが落としどころかもしれませんが,ちょっと悩み中。
それからシステムの一貫性ということを考えると,今はブログ用の権限やアイテム用の権限でシステムが最初から用意しているものは基本的にテーブルのフィールドを使うようにしていますが,このように名前を入れることを考えるとシステムロールと同じように中間テーブル形式だけにするのがいいのかも。フィールドはブラウズの権限だけをキャッシュ的に入れておくのに使うことにして。
ちなみに作業のほうはまだインストーラを作成中。database.ymlを作ったり,rake db:migrateでテーブル作るところまでWebのインタフェースでやってしまおうかと思っています。これでちゃんと動けばNucleus並みに簡単な設定で使えるようになります。
備忘メモ:タイムゾーン・サポート
現在のブログ・テーブルにはサーバーのローカルタイムからのオフセットを設定できるようになっているが,結構不便だ。サーバーがヨーロッパや米国など夏時間制を取るところにあると,日本のようにそうでないところとのオフセットが季節によって変わってしまうからだ。UTCとの差分を設定する方法もありえるが,今度は夏時間制を取っている地域で困ってしまう。
結局設定は地域名そのものにするしかないようだ。
幸い,Rails2.1ではTimezoneサポートとして様々な地域名が最初から登録されている。これをそのままテーブルに書き込むのが一番問題がなさそうだ。
インストーラを作成
改造ついでに寄り道してインストーラを作成しています。インストーラとはいっても実際にするのは言語設定と「Site Owner」の設定くらいですが。DBにテーブルを作るところはインストーラではなくrakeを使わざるを得ないので,その後に最初に走らせるプログラムということになります。気持ちとしてはウィザード風のユーザ・インタフェースにしたかったのですが,そういったデザイン・テンプレートが見つからなかったので管理画面のものを代用しています。