Takuji->find;

株式会社はてなでアプリケーションエンジニアやってます、技術的な記事を書いているつもり

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;