ガネー舎

新橋から少し歩いたところにあるガネー舎へスープカレーを食べに。 ちと入り口がわかりづらい。

ガネー舎

とりカリィを注文。

鳥カリィ

鶏は柔らかく、野菜はしゃっきり感があってうまい。
が、スパイシーさがもうちょっと欲しいかも。

graphvizでテーブルスキーマ

地道にそれっぽいのを用意しようとするならば、こんな感じ

digraph sample {
   graph [size = "6, 8"];   
   graph [nodesep = 0.7];
   node [shape = record, height = 0.01,   
         fontname = "Helvetica", fontsize = 9];

   bookmark [label = "{bookmark|id\nname\nuri\ndescription\ntime_created}"];
   tagmap [label = "{tagmap|id\nbookmark_id\ntag_id}"];
   tag [label = "{tag|id\nname}"];

   tagmap -> tag [label = "belongs_to"];
   tagmap -> bookmark [label = "belongs_to"];
   tag -> tagmap [label = "has_many"];
   tag -> tagmap [label = "many_to_many"];
   bookmark -> tagmap [label = "has_many"];
   bookmark -> tagmap [label = "many_to_many"];
}

dotコマンドで実行

$ dot -Tpng db.dot -o db_sample.png

many to many

もう少し、スキーマ図っぽくしたいなぁと色々探したらSQL::Translatorというものをみつけた。

後で試す。

男前マグネット

豆腐好きにはたまらないと評判の男前豆腐にガシャポンがでたと知ってから、密かにチェックしてたんだけど、先週末偶然イトーヨーカドーに立ち寄ったら見つけた。

ガシャポン(当時はガチャガチャ)まわすの、小学校以来だ。湯豆腐野郎とジョニーゲットして、帰って携帯につけようとしたら、ストラップじゃなくてマグネットだった。

残念。仕方ないので、家の冷蔵庫にくっつけておいた。

男前マグネット

イトーヨーカドーに結構設置されてるみたいね。

DBICで多対多

多対多のサンプルとしてTags: Database schemasの“Toxi” solutionをDBICで書いてみる。

関連を表すテーブルに対しては、1対多の関係を設定しておいて、更にmany_to_manyを追加する

図にしてみたらわかりやすくなった。

manytomany

ちなみに、1対多はこちらを、多対多はこちらを参考にしました。

Kzfm::Schema

use 5.008008;
use strict;
use warnings;
use base 'DBIx::Class::Schema';
our $VERSION = '0.01';

__PACKAGE__->load_classes(qw/Tag Bookmark TagMap/);

1;

Kzfm::Schema::Tag

use strict;
use warnings;
use base 'Kzfm::Schema';

__PACKAGE__->load_components(qw/PK::Auto::SQLite Core/);
__PACKAGE__->table('tag');
__PACKAGE__->add_columns(qw/id name/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(tagmap => 'Kzfm::Schema::TagMap','tag_id');
__PACKAGE__->many_to_many('bookmarks' => 'tagmap','bookmark_id');

1;

Kzfm::Schema::Bookmark

use strict;
use warnings;
use base 'Kzfm::Schema';

__PACKAGE__->load_components(qw/PK::Auto::SQLite Core/);
__PACKAGE__->table('bookmark');
__PACKAGE__->add_columns(qw/id name uri description time_created/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->has_many(tagmap => 'Kzfm::Schema::TagMap','bookmark_id');
__PACKAGE__->many_to_many('tags' => 'tagmap','tag_id');

1;

Kzfm::Schema::TagMap

use strict;
use warnings;
use base 'Kzfm::Schema';

__PACKAGE__->load_components(qw/PK::Auto::SQLite Core/);
__PACKAGE__->table('tagmap');
__PACKAGE__->add_columns(qw/id bookmark_id tag_id/);
__PACKAGE__->set_primary_key('id');
__PACKAGE__->belongs_to('bookmark_id' => 'Kzfm::Schema::Bookmark');
__PACKAGE__->belongs_to('tag_id' => 'Kzfm::Schema::Tag');

1;

制約の部分だけ、考えてみる。

__PACKAGE__->belongs_to('カラム名(アクセサ?)' => 'スキーマ(pm)');
__PACKAGE__->has_many(テーブル名 => 'スキーマ(pm)','カラム名(アクセサ?)');
__PACKAGE__->many_to_many('任意のキー名' => 'テーブル名','多対多関係のカラム');
  • belongs_toはまぁわかりやすい。
  • many_to_manyは任意にキー名決められるのにhas_manyはキー値にテーブル名指定しないとエラー吐くのが謎。
  • many_to_manyでテーブル名のとこをKzfm::Schema::TagMapってやるのが駄目な理由がよくわからない。

あと、さらにユーザーを追加する場合に、ユーザーとブックマークも多対多の関係になるけど、こっちも正規化したほうがいいのか、むしろやりすぎないほうがむしろいいのか悩む。

追記 06.12.04

ボケボケだったことに気付いた。

DBICで多対多の設定を

かなりボケボケだった。

こういうことらしい。

DBIx::Class::Relationship - Inter-table relationships - search.cpan.org

PACKAGE>$method_name('relname', 'Foreign::Class', $cond, $attrs);

というわけで、こんな感じの理解で。

__PACKAGE__->belongs_to(アクセサ名(任意) => 
    '従うクラス','従うクラスのIDを持つ属性名');
__PACKAGE__->has_many(アクセサ名(任意) => 
    'クラス','自分のクラスのIDをもつ属性名');
__PACKAGE__->many_to_many(アクセサ名(任意) => 
    'has_manyでのアクセサ名','belongs_toでのアクセサ名');

データベースを指しているのかクラスを属性を指してるのか良く分かってなかった。というかO/RマッパーでDBのカラム名っておかしいよって何で気づかなかったんだろう。

  • many_to_manyは任意にキー名決められるのにhas_manyはキー値にテーブル名指定しないとエラー吐くのが謎。
  • has_many(アクセサ名(任意) => 'クラス','カラム名')でOK
  • many_to_manyでテーブル名のとこをKzfm::Schema::TagMapってやるのが駄目な理由がよくわからない。
  • has_manyで指定したアクセサ名が必要なのでダメ。

なんとなくこんな感じか。

Hyper Estraier

あるとわかっているのに辿りつけないもどかしさというか、

google 検索結果返す 故にエントリ有り

というようなgoogle認識論的なアプローチに依存しすぎるということはちょっとツライことに気付いた。

ちゅうのは、自サイトの検索をgoogleに任せてからそこそこ経つんだけど、googleは被リンク数が少ないと(クローラーはガッツリ持ってくくせに)検索結果の表示対象にならない。そのため、自分で書いたエントリがあるはずなのに探せないという状況が頻発した。

なんで、やっぱ自前で検索エンジン入れる必要があるなぁと、Hyper Estraierを利用して検索できるようにした。

僕のサイトはblosxomで構築されている。これは、データベースでなく普通のテキストファイルでエントリを管理しているので、Hyper Estraierのestcmdでデータディレクトリを検索対象にすればよい。ただし、これだと、タイトル属性がないために、検索結果のタイトルがファイル名になってしまう。

blosxomのエントリデータは先頭行がタイトルのテキストデータなので、ここら辺をちょっといじくるblosxom用のフィルタを作成した。

まずは、フィルタを作成。/usr/local/share/hyperestraier/filterのestfxpdftohtmlをコピーしてフィルタを作成。下はdiffってみたけど、要するにpdftotextのコマンドをblosxom用のコンバートコマンドに書き換えれば良いだけ。僕の使っているestfxblosxomtohtml。

--- estfxpdftohtml      2006-12-02 16:09:34.000000000 +0900
+++ estfxblosxomtohtml  2006-12-02 17:47:04.000000000 +0900
@@ -1,14 +1,14 @@
 #! /bin/sh
 #================================================================
-# extfxpdftohtml
+# extfxblosxomtohtml
 # Convert PDF into HTML
 #================================================================

 # set variables
 PATH="$PATH:/usr/local/bin:$HOME/bin:." ; export PATH
-progname="estfxpdftohtml"
+progname="estfxblosxomtohtml"

 # check arguments
@@ -56,7 +56,7 @@

 # output the result
-pdftotext -enc UTF-8 -htmlmeta "$infile" - 2> "/dev/null" | output
+bldata2html "$infile" - 2> "/dev/null" | output

 # exit normally

で、blosxomのデータをhtmlに吐くには先頭行だけtitle属性で囲んで、あとはそのまま出力すればいいんだけど、僕はmarkdown使っているので、フィルタリングしてhtmlに出力するようなスクリプトにした。これがpdftotxtにあたるbldata2htmlで/usr/local/binとかのパスの通ったところに保存する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/perl

use strict;
use warnings;
use FileHandle;
use Text::Markdown 'markdown';

my $filename = shift;
my ($title,$body) = ();

my $fh = new FileHandle($filename);

$title = <$fh>;
chomp($title);

{
local $/ = undef;
$body = <$fh>;
}
my $html = markdown($body);

print "<title>", $title , "</title>\n", $html;

あとは、実際にインデックスをつくる。txt属性はestfxblosxomtohtmlフィルタをかますようにオプションを指定しておく。最後のextkeysは検索速度向上のため。

PATH=$PATH:/usr/local/share/hyperestraier/filter ; export PATH
estcmd gather -il ja -fx ".txt" "H@estfxblosxomtohtml" -sd casket /var/blosxom/data/
estcmd extkeys casket

で、実際にestseekで検索するといい感じ。後は定期的にインデックスの更新するようにしとけば、自サイトの検索はOK。今のとこ、cronでインデックスの更新するようにしていないので、blosomの検索フォームはgoogleのままだけど、そのうち変更しよう。

あとは、blosxomのエントリに類似エントリ検索をした結果を表示するプラグインを作っておけば便利かな。

markdownでコードを貼り付けるのは

markdownは行の先頭にスペース4文字を入れればcodeブロックになるので、

perl -ne 'print "    " . $_' file

とやった出力をblosxomのエントリにペーストしてるんだが、もうちょい楽な方法はないもんだろうか?
とか思った。

TTで空白行を除く

TT使ってできたHTMLのソースを見ると、IF文の部分とかが空白行になってしまい、やたらとスカスカ全開のHTMLが気持ち悪かったりして、コードの見やすさを犠牲にして、改行を削ってJAPHみたいなあとから読んだらよくわからんようなTT作ったりたんだけど、、、

-をつければchompして空白行を消すことができるということをCatalyst::Manual::Tutorial::CatalystBasicsで知った。

[% FOREACH book IN books -%]
  <tr>
    <td>[% book.title %]</td>
    <td>[% book.rating %]</td>
    <td>
    etc,etc
    </td>
  </tr>
[% END -%]
</table>

とかやっておくと

      </tr>

    </table>

といった、いかにもな感じの空白行が

      </tr>
    </table>

まるで手術痕の残らないヨみたいな自然なソースになるわけだ。素敵!

ま、ちょっと探したらTemplate Toolkit Manualにも書いてあったので、単にマニュアル読んでないのがばればれなだけなんだけど、、、、

Template Toolkit Manualもちゃんと読んでおくべきか。

で、微妙に本も欲しくなったりするなぁ。

ProductName Perl Template Toolkit
Darren Chamberlain
Oreilly & Associates Inc / 3031円 ( 2004-03 )


とはいうものの、TTに深入りするくらいなら、HTML::Masonみたいなほうが僕にはむしろあっているのかナァと悩んだが、テンプレートはテンプレートの利便さを追求する結果、うっかり高機能化した(しすぎた)だけなんだヨって考えるほうが、MVC的には自然なのかなあと今は考えている(というか自分を納得させている)。

TTSiteがうごかねーと悩んでいたら

久々にtelnetしたマシンでcatalystをいじってたら、TTSiteがうまく動かず、おかしいなぁ~と思ってたら

Catalystのバージョンが5.6902だった

このバージョンでTask::Catalyst 1.90を入れたので、エラーメッセージを吐かずに真っ白画面を出力していた模様。

Catalyst 5.7006にバージョンあげたらちゃんと動いた。

で、TTSiteだけど、普通に使うTTのヘルパーモードだと

app_create.pl view TT TT

で、TT.pmを作ってくれるだけなのに対してTTSiteは、

app_view TT TTSite

とやってヘルパーさんを動かすと、ヘッダー、フッターとかのテンプレートの雛型も一緒に作ってくれるという、お手軽度50%増量みたいな感じらしい。さらに、コントローラのディレクトリ構成とテンプレートのディレクトリの構成が対応するっぽいのでテンプレートが増えたときに把握しやすいのかも。

っていうか、これから使おうとしているのでまだちゃんとわかってないけど。

あとは、TTSiteだと拡張子がtt2になるので、Meadowのttモードも動くように.emacsに設定を追加しておく。

(setq auto-mode-alist
     (cons
       '("\\.tt2$" . html-helper-mode) auto-mode-alist))

Catalyst::Manual::Tutorialが充実してた

あれ、ちょっと見ない間に、チュートリアルが充実してた。

Catalyst::Manual::Tutorial

色々新しいことが書いてた。

  • DefaultEndはやめてCatalyst::Action::RenderView使うべし
  • TTSiteの使い方
  • CRUDをDBICで
  • AuthenticationとAuthorizationのやり方
  • デバッグとテスト
  • HTML::Widgetの使い方
  • flash featureの説明というか使いどころ

あたりは読んだけど、実際に何か作ってみないとちゃんと理解してるのかわからん。というわけで、DBICで多対多のdb使ってpubmed用のsbsを作り直してみることにした。Wikiに少しずつ書いてく予定。