Hatena::ブログ(Diary)

Senchan->find('all'); このページをアンテナに追加 RSSフィード Twitter

2011-06-13

TengのSchema生成スクリプトをちょっと賢くしてみた

DBIx::InspectorでTengのSchemaを生成する - Senchan->find(’all’);

以前書いたDBIx::Inspectorを使ったSchema生成スクリプトをちょっと賢くしてみた。

複合PKとかJSONのInflate/Deflateにも対応したり、そもそもInflate/Deflateが不要なテーブルにInflate/Deflateルールを書かなかったりと割と実用的になったつもり。

#! /usr/bin/env perl
use strict;
use warnings;

use DBIx::Inspector;
use lib './lib';

use Wagayatei::DB;
use Data::Section::Simple;
use Text::Xslate;
use Teng::Schema;
use Path::Class qw(dir);

my $dbi = Wagayatei::DB->get_dbi;

my $inspector = DBIx::Inspector->new( dbh => $dbi );
my $tables = [$inspector->tables()];

my $xslate = Text::Xslate->new(
    path => Data::Section::Simple->new->get_data_section,
    function => { column_exists => \&column_exists, to_array => \&to_array },
);

my $schema = $xslate->render('schema',{ tables => $tables, camelize => \&Teng::Schema::camelize });

my $path = dir('./')->subdir('lib/Wagayatei/DB/');
$path->mkpath;
my $fh = $path->file('Schema.pm')->openw;
print $fh $schema;
close $fh;

sub column_exists {
    my ( $pattern, $columns ) = @_;
    my @names = map { $_->name } @{$columns};
    my $exists = grep /$pattern/, @names;
    return $exists ? 1:0;
}

sub to_array {
    my $iter = shift;
    return [$iter->all];
}

1;
__DATA__
@@ schema
#XXX GENERATED BY generate_schema.pl
package  Wagayatei::DB::Schema;
use strict;
use warnings;


use Teng::Schema::Declare;
use Time::Piece::MySQL;
use JSON;

:for $tables -> $table {
    table{
        name '<: $table.name() :>';
        pk qw (
        : my $pks = to_array($table.primary_key)
        : for $pks -> $pk {
        <: $pk.name() :>
        : }
        );
        columns qw(
        :my $columns = to_array($table.columns())
        :for $columns -> $column {
            <: $column.name() :>
        : }
        );
        : if ( column_exists('_at$',$columns) ) {
        inflate qr/_at$/ => sub {
            Time::Piece->from_mysql_datetime(shift);
        };
        deflate qr/_at$/ => sub {
            shift->mysql_datetime;
        };
        : }
        : if ( column_exists('_data$',$columns) ) {
        inflate qr/_data$/ => sub {
            JSON->new->utf8->decode(shift);
        };
        deflate qr/_data$/ => sub {
            JSON->new->utf8->encode(shift);
        };
        : }
        row_class 'Wagayatei::Model::<: $camelize($table.name()) :>';
    };
:}

1;

2011-06-07

2011年06月07日のツイート

2011-06-06

2011年06月06日のツイート

Chiffonを書き直した

ChiffonのContainer依存とかその辺が割といけてない感じがしたので、Amon2を参考に書き直してみた

GitHub - takuji31/p5-Chiffon: Web application framework for PSGI/Plack

  • Chiffon::Coreを廃止、一部のユーティリティーメソッドはChiffon::Utilsに移動
  • Containerは非推奨に
  • DispatcherはRouterに名称変更、Dispatcher::Simple相当のモジュールは廃止、Dispatcher::RailsLike相当のものをデフォルト
  • ContextとChiffon.pmを統合
  • 例外クラスを追加、detachを置き換える
  • トリガー機能をモジュール

Chiffon::Coreを廃止

useすると勝手にuse strict;use warnings;してくれて、いくつかメソッドエクスポートしてくれるものだったが、微妙な感じがしたので廃止

メソッドのいくつかはChiffon::Utilsに移動した

Containerは非推奨に

プロジェクトにはContainerが必須だったが、微妙な感じがしたのでry

設定ファイルはChiffon::config()から、ホームディレクトリはChiffon->base_dirから読めるようになっている

DispatcherはRouterに名称変更、Dispatcher::Simple相当のモジュールは廃止、Dispatcher::RailsLike相当のものをデフォルト

基本的な設計はCakePHPのRouterを参考にした

Router部分のコードはRouter::Simpleを参考にしつつさらにシンプルにした感じ

ContextとChiffon.pmを統合、トリガー機能をモジュール

ここら辺はAmon2そのままですね、Amon2よりは柔軟性なくなってますが

例外クラスを追加、detachを置き換える

ほげほげしてdetach;してたのはすべてChiffon::Exception::HTTP::なにか で置き換えられるようになっているつもり

固定のヘッダー投げたかったらChiffon::Exception::HTTP継承したクラスを作るといいです(Flashとか)


前のものよりはきっと使いやすくなってるはずなので、是非使ってもらえると…

2011-04-27

DBIx::InspectorでTengのSchemaを生成する

久々に書いてみる

開発中のアプリでTeng使ってみようと考えたので簡単にSchema生成スクリプト書いてみた

_atがある前提だったり主キーは必ず1つだったり制約多い書き方だけどまぁ普通に使えるんじゃないかと思ってる

#! /usr/bin/env perl
use strict;
use warnings;

use DBIx::Inspector;
use lib './lib';

use Wagayatei::DB;
use Data::Section::Simple;
use Text::Xslate;
use Teng::Schema;
use Path::Class qw(dir);

my $dbi = Wagayatei::DB->get_dbi;

my $inspector = DBIx::Inspector->new( dbh => $dbi );
my $tables = [$inspector->tables()];

my $xslate = Text::Xslate->new(
    path => Data::Section::Simple->new->get_data_section,
);

my $schema = $xslate->render('schema',{ tables => $tables, camelize => \&Teng::Schema::camelize });

my $path = dir('./')->subdir('lib/Wagayatei/DB/');
$path->mkpath;
my $fh = $path->file('Schema.pm')->openw;
print $fh $schema;
close $fh;

1;
__DATA__
@@ schema
#XXX GENERATED BY generate_schema.pl
package  Wagayatei::DB::Schema;
use Chiffon::Core;

use Teng::Schema::Declare;
use Time::Piece::MySQL;

:for $tables -> $table {
    table{
        name '<: $table.name() :>';
        pk '<: $table.primary_key().next().name() :>';
        columns qw(
        :my $columns = $table.columns()
        :while $columns.next() -> $column {
            <: $column.name() :>
        :}
        );
        inflate qr/_at$/ => sub {
            Time::Piece->from_mysql_datetime(shift);
        };
        deflate qr/_at$/ => sub {
            shift->mysql_datetime;
        };
        row_class 'Wagayatei::Model::<: $camelize($table.name()) :>';
    };
:}

1;

2011-02-17

Acme::QB書いた

酔った勢いで書いた。反省はしていない。

takuji@sakura% perl -MAcme::QB -MPerl6::Say -e 'say QB->to_keiyaku';
僕と契約して、魔法少女になってよ!
takuji@sakura% perl -MAcme::QB -MPerl6::Say -Mutf8 -e 'my $a="プログラマー"; utf8::encode($a); say QB->to_keiyaku($a)'
僕と契約して、プログラマーになってよ!

これするだけのAcmeモジュール