mod_dav_svnでsvn

とりあえず何でも書くメソッドを実行してみる。結構後から自分で見たりするのよね。


いままでsvnをさくらでsvn+sshをやってたんですけどなぜか学内にProxyの規制が入ったらしく、「403 OK」なんてエラーを吐いてなぜか使えなくなってしまったのでどーせならapacheでいろいろやりたいなぁと思い試してみる。環境はdebian/etchで。

文を書くとえらく推敲してしまうので淡々とコマンドライン書くよ!。

sudo apt-get install libapache2-svn

これにmod_dav_svnとmod_authz_svnが入ってる。


で、/etc/apache2/mods-available/dav_svn.confを編集。以下抜粋。

<Location /svn>
  DAV svn
  SVNPath /var/svn/repos
</Location>

認証部分はあとでやる。もといきれいなコメント付いてるからコメントアウトするだけでよさそうだけど。

SVNPathをSVNParentPathにすればそのディレクトリ以下にあるレポジトリがそれぞれ動くようになる。
単数でいいならSVNPathでレポジトリの場所を指定。そして保存して再起動。

次にレポジトリを作る。順番逆な気もするけど気にしない。

cd /var
sudo mkdir svn
cd svn
sudo svnadmin create repos
cd ..
sudo chown www-data:www-data repos -R

レポジトリを作った後、apacheからアクセスできるようにwww-dataにユーザ、オーナを変更することに注意。それで、localhost/svn/reposにアクセスしたらRevision0って出る。これでおk。

あーーーー

まぁ私まだ学生の身分なので夏休みなんてものがあったわけですが、今日で終わりなわけですヴァー。
もともと日記は書くほうじゃないですけどたんぶらとついったいいですね、手軽に書けるからBlogとか書くのがめんどくさくなってくる。モジュールの振る舞いとか長く書きたいとき以外はあっちで済ませてしまってる。もとい学校始まったらBlogじゃないとかけないくらいのことをどんどんやっていきたいという抱負。


さて明日からはがんばらないとな。


誰が見るかわかりませんけどオレのついったとたんぶら貼っておきますね。

http://twitter.com/celeron1ghz
http://celeron1ghz.tumblr.com

たんぶらやべぇって。人が出るよね。

久しぶりにCatalyst

やっと一息つける時間だ。というわけで卒業研究に向けて軽くCatalystをいじってみる。APIプログラミングにしたいんでView::JSONでほげほげしてみるテスト。

とりあえずViewで作りますが、TT作る要領で

% script/testapp_create.pl view JSON JSON 

な感じでおっけ。さすがMVC


で、どう使っていくかですが、stashに入れるみたいですがどのkeyを使うかを
expose_stashで指定するみたいなのでconfigのyaml

View::JSON :
  expose_stash : TestValues

って書くとstash->{TestValues}が使われるみたいで。そして試しにこう書いて

sub test : Global   { 
    my ( $self, $c ) = @_; 
    $c->stash->{TestValues} = { Hash => "reference" }; 
    $c->forward( $c->view("JSON") );
}

localhost:3000/test ってやるとこうでます。

{"Hash":"reference"}

で、configを

View::JSON :
  expose_stash : 
    - TestValues

こうすると

{"TestValues":{"Hash":"reference"}}

こう返ってきます。なんかここらへんDBICみたい。

あと、expose_stashを変えたい場合(そんな場面ないよな、きっと)

$c->component('View::JSON')->{expose_stash};

なんてやると設定値getできるみたいです。つかcomponentをはじめて知った。
そしてモードかなんかで出力割り振りたい場合、

sub end : ActionClass('RenderView') {
    my ( $self, $c ) = @_;
    
    if ( $c->req->param("format") eq "json" )   {
        $c->forward( $c->view("JSON") );
    }   
} 

こんなん書いたら test?format=json って書いたらjson返ってきたよ。おっけおっけ。
RenderViewってこう使うのね。勉強になる。
とりあえずJSONは吐けたからあとはフォーマットとインターフェースかな。

わーー

Filter::RuleのDedupedってcompare_bodyってオプションあったのね!わーーー

=item compare_body

If set, this rule checks digest of entry, which is a MD5 hash of
entry's title with body. Defaults to 0.

=back

デフォルト0なのね。通りで静的HTML更新されないと思った。

joinとprefetch

ここまでやってそういやjoinなんてのあったよね、と思い出してなにが違うんだろうと思ってやってみる。前のエントリのコードのprefetchをjoinに置き換えて比較。


join

SELECT me.id, me.genre_name, me.place_name FROM master me  JOIN genre genre_name ON ( genre_name.genre_name = me.genre_name )  JOIN place place_name ON ( place_name.
place_name = me.place_name )  JOIN place_ref place_name_2 ON ( place_name_2.place_ref_name = place_name.place_name ):
SELECT me.genre_name FROM genre me WHERE ( ( ( me.genre_name = ? ) ) ): 'genre1'
genre1 at t.pl line 10.
SELECT me.place_name FROM place me WHERE ( ( ( me.place_name = ? ) ) ): 'place1'
SELECT me.place_ref_name FROM place_ref me WHERE ( ( ( me.place_ref_name = ? ) ) ): 'place1'
place1 at t.pl line 11.


prefetch

SELECT me.id, me.genre_name, me.place_name, place_name.place_name, place_name_2.place_ref_name, genre_name.genre_name FROM master me  JOIN place place_name ON ( plac
e_name.place_name = me.place_name )  JOIN place_ref place_name_2 ON ( place_name_2.place_ref_name = place_name.place_name )  JOIN genre genre_name ON ( genre_name.ge
nre_name = me.genre_name ):
genre1 at t.pl line 10.
place1 at t.pl line 11.

joinは単純にjoinしてるだけなのね(当たり前)
joinはケースに応じて表示するものが変わる物に、prefetchは全表示のときに使うみたいな感じなのかな。

あけました、でDBIC

あけましておめでとうございます。ちょっと遅いかもしれませんが。
今年もバリバリPerlっていきたいです。


というわけでDBIC
Catalystアプリで作ってたんですけどよく使い方がわからないのでDBIC単体でいじくり倒そうかと。


まずはテーブル。

CREATE TABLE genre
( genre_name VARCHAR(8) NOT NULL PRIMARY KEY );
CREATE TABLE place
( place_name VARCHAR(8) NOT NULL PRIMARY KEY );

CREATE TABLE master	(
	id INTEGER(5) NOT NULL PRIMARY KEY AUTO_INCREMENT,
	genre_name VARCHAR(8) NOT NULL,
	place_name VARCHAR(8) NOT NULL,

	FOREIGN KEY (genre_name) REFERENCES genre(genre_name),
	FOREIGN KEY (place_name) REFERENCES place(place_name)
);

INSERT INTO genre VALUES ("genre1");
INSERT INTO genre VALUES ("genre2");

INSERT INTO place VALUES ("place1");
INSERT INTO place VALUES ("place2");

INSERT INTO master VALUES (NULL, "genre1", "place1");

masterテーブルがただgenreとplaceを両方見ているだけのテーブル。


DBICスキーマ作成はここらへんを参考にしてパパッと作っちゃいましょう。で、これを

use MySchema;

BEGIN{ $ENV{DBIC_TRACE} = 1 }

my $s	= MySchema->connect(qw/dbi:mysql:sand foo pass/);
my $m	= $s->resultset("Master");
my $it	= $m->search;

while ( my $i = $it->next )	{
	warn $i->genre_name->genre_name;
	warn $i->place_name->place_name;
}


で、出力を見ると、

SELECT me.id, me.genre_name, me.place_name FROM master me:
SELECT me.genre_name FROM genre me WHERE ( ( ( me.genre_name = ? ) ) ): 'genre1'
genre1 at t.pl line 10.
SELECT me.place_name FROM place me WHERE ( ( ( me.place_name = ? ) ) ): 'place1'
place1 at t.pl line 11.

と、genreとplaceの両方に対してSQLを発行してます。数が少ないといいですけど多くなってきて全件表示とかやるとイヤンな感じ。
こういう単純なときはprefetchを使うとSQLの発行回数を減らせる。というか名前通りですけど。

#prefetchを加える
my $it	= $m->search(undef, { prefetch => "genre_name"  } );
SELECT me.id, me.genre_name, me.place_name, genre_name.genre_name FROM master me  JOIN genre genre_name ON ( genre_name.genre_name = me.genre_name ):
genre1 at t.pl line 10.
SELECT me.place_name FROM place me WHERE ( ( ( me.place_name = ? ) ) ): 'place1'
place1 at t.pl line 11.


文字通り減ってます。perldocみると($rel_name | \@rel_names | \%rel_names)と書いてあるので

my $it	= $m->search(undef, { prefetch => [ qw/genre_name place_name/ ] } );
SELECT me.id, me.genre_name, me.place_name, genre_name.genre_name, place_name.place_name FROM master me  JOIN genre genre_name ON ( genre_name.genre_name = me.genre_
name )  JOIN place place_name ON ( place_name.place_name = me.place_name ):
genre1 at t.pl line 10.
place1 at t.pl line 11.

なんてやると発行回数減ります。詳細表示とか表示するのにいい感じ。


ついでにHashも。テーブルのリレーションを増やす。placeテーブルが参照するplace_refテーブルを作るとか言うお粗末な感じで :-p

CREATE TABLE place_ref
( place_ref_name VARCHAR(8) NOT NULL PRIMARY KEY );
CREATE TABLE place
(
  place_name VARCHAR(8) NOT NULL PRIMARY KEY,
  FOREIGN KEY (place_name) REFERENCES place_ref(place_ref_name)
);

INSERT INTO place_ref VALUES ("place1");
INSERT INTO place_ref VALUES ("place2");
INSERT INTO place VALUES ("place1");
INSERT INTO place VALUES ("place2");
SELECT me.id, me.genre_name, me.place_name, genre_name.genre_name, place_name.place_name FROM master me  JOIN genre genre_name ON ( genre_name.genre_name = me.genre_
name )  JOIN place place_name ON ( place_name.place_name = me.place_name ):
genre1 at t.pl line 10.
SELECT me.place_ref_name FROM place_ref me WHERE ( ( ( me.place_ref_name = ? ) ) ): 'place1'
MySchema::PlaceRef=HASH(0x1f5fa6c) at t.pl line 11.

スキーマ変えたのでDBICスキーマも作り直しましょう。


placeテーブルをplace_refに参照するようになってるのでもちろんHashRefになってます。そこでもう一回メソッド呼び出すとSQLが発行されてしまうのでprefetchを設定。

my $it	= $m->search(undef, { prefetch => [ qw/genre_name /,{place_name=>"place_name"} ] } );

while ( my $i = $it->next )	{
	warn $i->genre_name->genre_name;
	warn $i->place_name->place_name->place_ref_name;
}
SELECT me.id, me.genre_name, me.place_name, place_name.place_name, place_name_2.place_ref_name, genre_name.genre_name FROM master me  JOIN place place_name ON ( plac
e_name.place_name = me.place_name )  JOIN place_ref place_name_2 ON ( place_name_2.place_ref_name = place_name.place_name )  JOIN genre genre_name ON ( genre_name.ge
nre_name = me.genre_name ):
genre1 at t.pl line 10.
place1 at t.pl line 11.

おー適当にやったら出来てしまった。ここでのprefetchのHashRefのkeyはplaceテーブルの項目、valueはplace_refのaliasでいいのかな?
DBICのメソッド全般に言えることっぽいですがScalarRef,ArrayRef,HashRefを入れてやると適正に処理してくれるみたいですね。ここでも通じると。なかなか手ごわそうですDBIC

いまCataその2

先にV

controllerを書ききってしまおうと思ったんですが、TTSiteってヘルパが面白かったんでこっちが先に。
とりあえず引数は'view'、作る名前、使うヘルパ名みたいなので、3つめにTTSiteを指定してやってみる。

とりあえずヘルパースクリプトに作れ!といえば作ってくれるのでとりあえず作る。

z:\testBBS\script>perl testbbs_create.pl view TT TTSite
#以下ずらーっと
で、中身

聞いていた通り、HTMLのデザインに必要なもの+分離されたTTのファイルが作られてます。
作ったTTのスケルトンを見ると、root/libとroot/srcにいろいろなファイルが作られていて、そこにTemplateのINCLUDEパスが通っている模様。
libが色とか外枠などの定義、srcには実際controller内にで使うものを作ったり置いたりみたいです。

順番的に

  • PRE_PROCDESSでroot/lib/config/mainが読まれる
  • root/lib/config/main/col が処理され、(CSSの色定義)
  • root/lib/config/main/url が処理され、(baseとhomeとmessageとかリンクや表示に必要と思われるものの定義)

ここで色や名前とかを定義しておけば、このあと処理されるファイルで展開されます。そして

  • WRAPPERでroot/lib/site/wrapperが読まれる
  • root/lib/site/htmlが読まれ
  • root/src/ttsite.cssが読まれ
  • root/lib/site/layoutが読まれ
  • root/lib/site/headerが読まれ
  • root/lib/site/footerが読まれ


あとはstashに指定したテンプレートファイルが今まで処理されてきたものに埋められて処理するみたい。つまり作るテンプレートはbodyタグ内にあるって考えればいいっぽい。
わかりにくいから図で説明。

< col(変数定義)>
< url(変数定義)>
<
  html
  < ttcite.css >
  <
    layout
    < header >
    < ここに指定したテンプレートが埋まる >
    < footer >
  >
>

こんな感じなのかな。ざっくり作っちゃいたい場合に便利。