Customization of DBIC::Schema::Loader

100 %
0 %
Information about Customization of DBIC::Schema::Loader

Published on April 23, 2008

Author: zigorou

Source: slideshare.net

Customization DBIC::Schema::Loader d:id:ZIGOROu Toru Yamaguchi <zigorou@cpan.org>

Agenda DBIC::Schema::Loader のおさらい make_schema_at() 生成されたファイル自体に拡張 inc パスの追加による拡張 really_erase_files の値 Schema クラスも拡張対象にする DBIC::Schema::Loader を改造 DBIC::Schema::Loader の概要 名前に制約をつけてリレーション設定 まとめ

DBIC::Schema::Loader のおさらい

make_schema_at()

生成されたファイル自体に拡張

inc パスの追加による拡張

really_erase_files の値

Schema クラスも拡張対象にする

DBIC::Schema::Loader を改造

DBIC::Schema::Loader の概要

名前に制約をつけてリレーション設定

まとめ

make_schema_at() DBIC::Schema::Loader のメソッド 引数 1. schema クラス名 2. 生成オプション (HASHREF) 3. connect_info (ARRAYREF) 基本系 #!/usr/bin/perl use FindBin; use File::Spec; use DBIx::Class::Schema::Loader qw(make_schema_at) ; make_schema_at( 'MyApp::DBIC::Schema' , { dump_directory => File::Spec->catfile( $FindBin::Bin , '..' , 'lib' ), relly_erase_files => 1 , }, [ 'dbi:mysql:database=dbictest' , 'root' ], );

DBIC::Schema::Loader のメソッド

引数

1. schema クラス名

2. 生成オプション (HASHREF)

3. connect_info (ARRAYREF)

基本系

#!/usr/bin/perl

use FindBin;

use File::Spec;

use DBIx::Class::Schema::Loader qw(make_schema_at) ;

make_schema_at( 'MyApp::DBIC::Schema' , {

dump_directory => File::Spec->catfile( $FindBin::Bin , '..' , 'lib' ),

relly_erase_files => 1 , },

[ 'dbi:mysql:database=dbictest' , 'root' ],

);

拡張 (1) ファイル直書き方式 - 1 生成されたファイルに拡張 生成された Schema, Table クラスそれぞれの下の方に “ DO NOT MODIFY THIS ” と書かれたコメントがある そこから “ You can replace this text ” の領域は拡張領域で自動生成の対象ではない 生成されたファイルに直接書いて良い 追加で load_components() したりとか あるいは他のプラグインのメソッド叩いたり テーブル定義をゴニョゴニョしたりとか

生成されたファイルに拡張

生成された Schema, Table クラスそれぞれの下の方に “ DO NOT MODIFY THIS ” と書かれたコメントがある

そこから “ You can replace this text ” の領域は拡張領域で自動生成の対象ではない

生成されたファイルに直接書いて良い

追加で load_components() したりとか

あるいは他のプラグインのメソッド叩いたり

テーブル定義をゴニョゴニョしたりとか

拡張 (1) ファイル直書き方式 - 2 # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:WFbbTfTFDFr/kewSj3QwAw package MyApp::DBIC::Schema; __PACKAGE__->load_components( qw/+MyApp::DBIC::MyComp/ ); __PACKAGE__->init_mycomp; # You can replace this text with custom content, and it will be preserved on regeneration 1 ;

# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:WFbbTfTFDFr/kewSj3QwAw

package MyApp::DBIC::Schema;

__PACKAGE__->load_components(

qw/+MyApp::DBIC::MyComp/

);

__PACKAGE__->init_mycomp;

# You can replace this text with custom content, and it will be preserved on regeneration 1 ;

拡張 (2) incにあるテンプレ読み込み方式 - 1 incパスに通したテンプレからinclude use libで適当なディレクトリにパスを通すと、そこにあるファイルを対応するモジュールの拡張領域に差し込んでくれる機能 ここで注意しないとダメなのはSchemaクラスは対象外 Tableクラスのみ拡張可能 ちなみに拡張領域の箇所はファイル直書き方式と同じ

incパスに通したテンプレからinclude

use libで適当なディレクトリにパスを通すと、そこにあるファイルを対応するモジュールの拡張領域に差し込んでくれる機能

ここで注意しないとダメなのはSchemaクラスは対象外

Tableクラスのみ拡張可能

ちなみに拡張領域の箇所はファイル直書き方式と同じ

拡張 (2) incにあるテンプレ読み込み方式 - 2 ディレクトリ構成 lib MyApp DBIC Schema User.pm schema MyApp DBIC Schema User.pm 自動生成される領域 Include ( ファイルの下部にくっつく )

ディレクトリ構成

make_schema_at() [2] really_erase_files ( 生成オプション ) true の時 毎回ファイルを消して生成する Schema, Table クラス両方消しちゃうので、 ファイル直書き方式は使えない >< 必然的に include になるが、 Schema に対しては適用出来ない false の時 毎回ファイルを消さない 直書き方式が使える 但し消さないと include で挿入されたブロックが次回の直書きと見なされ、再び include されるので重複コードになるwww

really_erase_files ( 生成オプション )

true の時

毎回ファイルを消して生成する

Schema, Table クラス両方消しちゃうので、 ファイル直書き方式は使えない ><

必然的に include になるが、 Schema に対しては適用出来ない

false の時

毎回ファイルを消さない

直書き方式が使える

但し消さないと include で挿入されたブロックが次回の直書きと見なされ、再び include されるので重複コードになるwww

ここまでのまとめ 現在の問題点 Schema, Table 共に後付的に拡張したい Schema も対象にするなら really_erase_files を false にする そうすると直書き領域に make_schema_at する度に重複するコードが出来てしまう どうすれば良いか really_erase_files => 0 でも自分で Table クラスを消せば同じ事になる 拡張は Schema は直書き、 Table は include でやる。

現在の問題点

Schema, Table 共に後付的に拡張したい

Schema も対象にするなら really_erase_files を false にする

そうすると直書き領域に make_schema_at する度に重複するコードが出来てしまう

どうすれば良いか

really_erase_files => 0

でも自分で Table クラスを消せば同じ事になる

拡張は Schema は直書き、 Table は include でやる。

改良版Schema生成 改良版 #!/usr/bin/perl use strict ; use warnings ; use FindBin; use File::Spec; use lib ( File::Spec->catfile( $FindBin::Bin , qw/.. lib/ ), File::Spec->catfile( $FindBin::Bin , qw/.. schema/ ) ); use DBIx::Class::Schema::Loader qw(make_schema_at) ; die unless @ARGV ; my $schema_class = 'MyClass::DBIC::Schema' ; # こんな感じで自分で消す unlink ( glob ( File::Spec->catdir( $FindBin::Bin , '..' , 'lib' , split ( / :: / , $schema_class ) ) . '/*.pm' ) ); make_schema_at( $schema_class , { components => [ qw/ResultSetManager UTF8Columns InflateColumn::DateTime TimeStamp/ ], dump_directory => File::Spec->catfile( $FindBin::Bin , qw/.. lib/ ), debug => 0 , really_erase_my_files => 0 , }, @ARGV );

改良版

#!/usr/bin/perl

use strict ;

use warnings ;

use FindBin;

use File::Spec;

use lib (

File::Spec->catfile( $FindBin::Bin , qw/.. lib/ ),

File::Spec->catfile( $FindBin::Bin , qw/.. schema/ )

);

use DBIx::Class::Schema::Loader qw(make_schema_at) ;

die unless @ARGV ;

my $schema_class = 'MyClass::DBIC::Schema' ;

# こんな感じで自分で消す

unlink ( glob ( File::Spec->catdir( $FindBin::Bin , '..' , 'lib' , split ( / :: / , $schema_class ) ) . '/*.pm' ) );

make_schema_at(

$schema_class ,

{

components => [ qw/ResultSetManager UTF8Columns InflateColumn::DateTime TimeStamp/ ],

dump_directory => File::Spec->catfile( $FindBin::Bin , qw/.. lib/ ),

debug => 0 ,

really_erase_my_files => 0 ,

},

@ARGV

);

さらなる改良 Schema::Loader について 中で何やってるか理解すればもっとカスタマイズ出来そう 特にリレーションとか通常の使い方では手出しできない部分を何とかしたい まずはクラス図から

Schema::Loader について

中で何やってるか理解すればもっとカスタマイズ出来そう

特にリレーションとか通常の使い方では手出しできない部分を何とかしたい

まずはクラス図から

Class::Diagram of DBIC::Schema::Loader Class Diagram DBIC::Schema::Loader DBIC::Schema ::Loader::Base DBIC::Schema ::Loader::Base::DBI::mysql DBIC::Schema ::Loader::RelBuilder 各ドライバごとにクラスがある リレーションの構築 Dump 時のオプションの詳細

Class Diagram

RelationShip [1] belongs_to とか has_many とか belongs_to(“user_id”, ...) $rs-> user_id -> user_id ダサすぎ 残念ながら現在はこうなる belongs_to(“user”, ...) $rs-> user -> user_id $rs-> user_id も OK 自然になる こうしたい

belongs_to とか has_many とか

belongs_to(“user_id”, ...)

$rs-> user_id -> user_id

ダサすぎ

残念ながら現在はこうなる

belongs_to(“user”, ...)

$rs-> user -> user_id

$rs-> user_id も OK

自然になる

こうしたい

RelationShip [2] 問題の箇所 DBIC::Schema::Loader::Base の _load_relationship() foreach my $src_class ( sort keys %$rel_stmts ) { my $src_stmts = $rel_stmts ->{ $src_class }; foreach my $stmt ( @$src_stmts ) { ### ここら辺を書き換えちゃえば良い $self ->_dbic_stmt( $src_class , $stmt ->{method}, ## belongs_to とか @{ $stmt ->{args}} ## belongs_to の引数リスト ); } }

問題の箇所

DBIC::Schema::Loader::Base の _load_relationship()

foreach my $src_class ( sort keys %$rel_stmts ) {

my $src_stmts = $rel_stmts ->{ $src_class };

foreach my $stmt ( @$src_stmts ) {

### ここら辺を書き換えちゃえば良い

$self ->_dbic_stmt(

$src_class , $stmt ->{method}, ## belongs_to とか

@{ $stmt ->{args}} ## belongs_to の引数リスト

);

}

}

RelationShip [4] 改良版 foreach my $src_class ( sort keys %$rel_stmts ) { my $src_stmts = $rel_stmts ->{ $src_class }; foreach my $stmt ( @$src_stmts ) { ### belongs_to の時だけ無茶する if ( $stmt ->{method} eq 'belongs_to' ) { my $table_class_suffix = [ split / :: / => $stmt ->{args}->[ 1 ] ]->[ -1 ]; $stmt ->{args}->[ 0 ] = String::CamelCase::decamelize( $table_class_suffix ); } $self ->_dbic_stmt( $src_class , $stmt ->{method}, @{ $stmt ->{args} } ); } }

改良版

foreach my $src_class ( sort keys %$rel_stmts ) {

my $src_stmts = $rel_stmts ->{ $src_class };

foreach my $stmt ( @$src_stmts ) {

### belongs_to の時だけ無茶する

if ( $stmt ->{method} eq 'belongs_to' ) {

my $table_class_suffix = [

split / :: / => $stmt ->{args}->[ 1 ]

]->[ -1 ];

$stmt ->{args}->[ 0 ] =

String::CamelCase::decamelize( $table_class_suffix );

}

$self ->_dbic_stmt( $src_class , $stmt ->{method}, @{ $stmt ->{args} } );

}

}

まとめ Schema::Loader との付き合いかた really_erase_files を false でも自分で Table 消す Schema は直書き、 Table は include で辻褄合わせる belongs_to は問題箇所を redifine する 名前でコード生成時の制約をつけるのは良さそう。 on_created, on_updated(DATETIME) で NOW() 相当とか 時間の都合上割愛したけど、それ以上は自分で DBIC 流儀のプラグイン書く ( 割と便利 ) そこまでするなら自分で Loader 書くべき?(ぇ あるいは DBIC を使わない

Schema::Loader との付き合いかた

really_erase_files を false

でも自分で Table 消す

Schema は直書き、 Table は include で辻褄合わせる

belongs_to は問題箇所を redifine する

名前でコード生成時の制約をつけるのは良さそう。 on_created, on_updated(DATETIME) で NOW() 相当とか

時間の都合上割愛したけど、それ以上は自分で DBIC 流儀のプラグイン書く ( 割と便利 )

そこまでするなら自分で Loader 書くべき?(ぇ

あるいは DBIC を使わない

おしまい ご清聴ありがとうございました

ご清聴ありがとうございました

Add a comment

Related presentations

Related pages

Customization of Location Part 18 - Documents

Customization of Location, United Kingdom Address Style,Location Customization, Segments, Business Group, Oracle HRMS, oraclehrms, Business Group Location ...
Read more

Joomla customization: add more features of your ...

... Joomla customization development is an excellent option that allows people to customize their website with their required features. ...
Read more

Cultural Customization of Websites for Japanese ...

Cultural Customization of Websites for Japanese Subsidiaries of Global Companies Jan 25, 2015 Education tricho. System is processing data
Read more

Automatic Customization of Non-Player Characters Using ...

Slide 1 Automatic Customization of Non-Player Characters Using Players Temperament Kyle Li Slide 2 REFERENCE Automatic Customization of Non-Player ...
Read more

Local Customization Chapter 2. Local Customization 2-2 ...

Local Customization Chapter 2. Local Customization 2-2 Objectives Customization Considerations Types of Data Elements Location for Locally Defined Data.
Read more