2007年5月アーカイブ

2007年5月27日

いや、perlが5.8になってから、utf-8フラグがらみで、面倒なことばっかりだな。と、正直思ってたんです。

でも、考えを改めてもいい。正直そう思った。

たとえば、「スペースで区切って、複数のワードを入力する」というインターフェースがあった場合、「スペース」がすべていわゆる半角スペースであると仮定すれば、splitでわけるだけですよね。インターフェースの都合上、いわゆる全角スペースが混じってしまう可能性があるとすると、その全角のスペースを一旦半角スペースに変換してからsplitしないとだめになるわけですよ。

ところが、split( /[\x{0020}\x{3000}]/, $input )ってやるだけで、$inputがUTF8フラグ付なら、一発でわけることができるわけですね。ちゃんと「バイト列」ではなくて「文字列」として扱ってつわけですな。

でも、逆に、面倒なのが、バイト列として扱うときの操作。たとえば、urlで許されない文字をaタグなんかにつかうときにつかう、%xx%xxというあれですね。

sub my_encode{
  my $tmp = shift;
  $tmp = Encode::encode('utf8',$tmp);
  $tmp =~ s/([^\w])/'%'.unpack("H2", $1)/ego;
  $tmp =~ tr/ /+/;
  $tmp = Encode::decode('utf8',$tmp);
  return $tmp;
}

ってな感じに、文字列ではなくバイト列として扱うように、UTF8フラグを外してから変換してUTF8フラグを立てるという処理にしなくてはいけません。文字列のままだと[^\w]が1バイトとは限らないので、unpackのH2の2がダメになってしまうからですね。

これもはまりました。それにしても、「はまる」ということすら、楽しくなってくるというのが、プログラムを書く楽しみと言えるのでしょうか。山登りみたいなもんですかね……

2007年5月26日

7ヶ月、と、もうすぐ5ヶ月の2人の赤ちゃんが、うちに遊びに来てくれました。

7ヶ月の赤ちゃんは、自在にはいはいできるので、機動力も抜群でしたが、おもちゃの取り合いになると、なぜか、動けないはずのうちの坊主が勝つ。という謎展開。

もうすぐ5ヶ月の赤ちゃんの初寝返りに立ち会うなど、なかなかの楽しい展開。

また、やりましょう。

2007年5月25日

Class::DBIは、いろんな意味で最高なのですが、many_to_manyのリレーションを作るどうやればいいんだろうなぁ。と、いろいろ検索して、見つけたのが、ξ;゜ー゜)ξ { 遅レス。 - Class::DBI(CDBI)で多対多(many_to_many)

そういえば、大昔、というか、前の(?)会社の時に、先輩が、そういう風にテーブルを作っていたなぁ、と懐かしくなったりしつつ、いろいろ利用。ところが、なんかうまくいかないです。

結論から言うと、Complex many to many - ClassDBIのように、中間テーブルには、idカラムというか、「複合ではないプライマリキー」が必要でした。

リンク先の例にならうと、

CREATE TABLE Users (
    code    varchar(8)   primary key,
    passwd  varchar(255) not null
);

CREATE TABLE CourseUsers ( id varchar(8) primary key, user_code varchar(8) not null, course_code varchar(255) not null, unique (user_code, course_code) );
CREATE TABLE Courses ( code varchar(5) primary key, name varchar(255) not null );
package MyApp::Model::CDBI; use strict; use base 'Class::DBI::SQLite'; __PACKAGE__->set_db('Main', 'dbi:SQLite:dbname=/path/to/dbfile');
package MyApp::Model::CDBI::Users; use strict; use base 'MyApp::Model::CDBI';
__PACKAGE__->set_up_table('Users'); __PACKAGE__->has_many(courses => ["MyApp::Model::CDBI::CourseUsers" => 'course_code'], 'user_code');
package MyApp::Model::CDBI::CourseUsers; use strict; use base 'MyApp::Model::CDBI';
__PACKAGE__->set_up_table('CourseUsers'); __PACKAGE__->has_a(course_code => "MyApp::Model::CDBI::Courses"); __PACKAGE__->has_a(user_code => "MyApp::Model::CDBI::Users"); sub courses { shift->user->courses } sub users { shift->course->users }
package MyApp::Model::CDBI::Courses; use strict; use base 'MyApp::Model::CDBI';
__PACKAGE__->set_up_table('Courses'); __PACKAGE__->has_many(users => ["MyApp::Model::CDBI::CourseUsers" => 'user_code'], 'course_code');

たぶん、こんな感じ。

なんというか、結局のところ、本家の情報を英語だからといって避けたりしないでちゃんと読め。ってことなんだろうなぁ……

2007年5月23日

WWW::Mechanizeを利用して、ちょっとしたものを作成していたんですが、なぜが文字が化けてしまって、おかしいなぁ。この化け方って、どう考えても、utf-8に変換するときの問題だよな……。と思って探したら、WWW::Mechanize中に、こんなコードが……

# Try to decode the content. Undef will be returned if there's nothing to decompress.
# See docs in HTTP::Message for details. Do we need to expose the options there?
my $content = $res->decoded_content;
   $content = $res->content if (not defined $content);

decoded_contentは、HTTP::Messageにあって、

if ($ct && $ct =~ m,^text/,,) {
    my $charset = $opt{charset} || $ct_param{charset} || $opt{default_charset} || "ISO-8859-1";
    $charset = lc($charset);
    if ($charset ne "none") {
	require Encode;
	if (do{my $v = $Encode::VERSION; $v =~ s/_//g; $v} < 2.0901 &&
	    !$content_ref_iscopy)
	{
	    # LEAVE_SRC did not work before Encode-2.0901
	    my $copy = $$content_ref;
	    $content_ref = \$copy;
	    $content_ref_iscopy++;
	}
	$content_ref = \Encode::decode($charset, $$content_ref, Encode::FB_CROAK() | Encode::LEAVE_SRC());
    }
}

となっているので、Content-Typeが、text/....だったら、デフォルトはISO-8859-1としてEncode::decode、つまりUTF-8に変換しUTF-8フラグを立てることになるわけですな。そりゃ、文字化けもするよ……。

てか、オプションいるかい?じゃなくて、大至急何とかしろよ。と、思いつつも、ラッパークラスを作って対応。

そういえば、WWW::Mechanizeの1.22(現在のNetBSD pkgsrcの最新)より新しいバージョンはあるのかな?とcpanを探してみたら、最新の1.24では該当コードが削除されていて、開発版の1.29_01では

# Try to decode the content. Undef will be returned if there's nothing to decompress.
# See docs in HTTP::Message for details. Do we need to expose the options there? 
# use charset => 'none' because while we want LWP to handle Content-Encoding for 
# the auto-gzipping with Compress::Zlib we don't want it messing with charset
my $content = $res->decoded_content( charset => 'none' );
   $content = $res->content if (not defined $content);

と、なっていた。たしかに、そうよね……。さて、default_charsetをutf-8として指定するようにラッパークラスを書いてしまった私は、どうすればいいんだろう……。ま、得られた結果をutf-8としてencodeしてやればいいだけ……なの?かな?

あと、Class::DBI::Pagerを使っていて、1ページから最終ページまでじゃなくて、gooooogleみたいに、カレントページの周辺10ページにリンクを張るみたいなコトできないだろうか?と、調べてみたんだけど、よくわからない。

ただ、Changesに書いてある、Data::Page::Navigationってのが、それっぽくて、しかも、supportと書いてあるけれど、イマイチ使い方がよくわからないな。

Class::DBI::Pagerを継承する俺クラスでuse Data::Page::Navigationするってこと?なの?かな?でも、それって、supportなの?わからないね

なんにしても、プログラムを書くということは、たのしいものですな。それにしても、今さらながら、Class::DBIすげー。とか、ほんと、思う。

2007年5月18日

最初の事例が、3歳の男の子。しかも、父親に「かくれんぼしよう」って言われたとか……。

子供を捨てなければやっていけない。と判断した理由だとか、いろいろ知りたいことはあるけれど、3歳になるまで健康に育ててきた人だからこそ、こういう施設を利用することを思いついたんだろうなぁ。

でも、こういう施設を頼らなければならなくなったという状況が非常にやばいとおもう。これって、「最後の手段」なので、それ以前の行政サービスで対応できなかったことを、各自治体と国は反省すべき何じゃないだろうか?

親を責めるのは簡単だ。親学だかなんだか知らないが、あるべき論を振りかざすだけで、現実問題として、子供を育てていく環境が今どうなっているのか、ちゃんとみてほしいものだ……。

でも、大阪の座席下のスペースに子供を入れた。というあの親は責めていいと思うよ。

2007年5月15日

風邪が全然治らないのです

そんななか、日々、謎プログラムを作り、謎ページでいろいろ。という感じで、ちょっと、ニコ中だったりします。やばいね。

2007年5月 5日

激しく風邪ひいた。

GW前から、ノドが痛いな。とは、思っていたんですが、発熱、鼻水な感じで、どうもいけません。

2007年5月 2日

大阪から、両親がやってきましたよ。

ハイテンションな両親にあわせて、うちの息子さんは、いつもにもましてハイテンションです。そんななか、両親とスタジオアリスに行って大散財。てか、あれよね。入るのはタダだけど、出るのは高いよ。って感じだ

大きくなったなぁ。などと申しておりましたが、そりゃそうだ、両親がうちの息子にあったのは、約半年前、生まれた直後のことですよ。そんなこんなで、半年ぶりに孫を満喫して帰って行かれましたよ。