Customization of DBIC::Schema::Loader
-
Upload
toru-yamaguchi -
Category
Technology
-
view
2.135 -
download
1
description
Transcript of Customization of DBIC::Schema::Loader
catalyst conference #1
Customization DBIC::Schema::Loader
Customization DBIC::Schema::Loader
d:id:ZIGOROu
Toru Yamaguchi <[email protected]>
Apr 10, 2023 2
AgendaAgenda
DBIC::Schema::Loader のおさらい make_schema_at()
生成されたファイル自体に拡張 inc パスの追加による拡張 really_erase_files の値 Schema クラスも拡張対象にする
DBIC::Schema::Loader を改造 DBIC::Schema::Loader の概要 名前に制約をつけてリレーション設定
まとめ
Apr 10, 2023 3
make_schema_at()make_schema_at()
DBIC::Schema::Loader のメソッド 引数
1. schema クラス名 2. 生成オプション (HASHREF) 3. connect_info (ARRAYREF)
基本系#!/usr/bin/perluse 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'], );
Apr 10, 2023 4
拡張 (1) ファイル直書き方式 - 1拡張 (1) ファイル直書き方式 - 1
生成されたファイルに拡張 生成された Schema, Table クラスそれぞ
れの下の方に “ DO NOT MODIFY THIS” と書かれたコメントがある そこから “ You can replace this text” の領域
は拡張領域で自動生成の対象ではない 生成されたファイルに直接書いて良い
追加で load_components() したりとか あるいは他のプラグインのメソッド叩いたり テーブル定義をゴニョゴニョしたりとか
Apr 10, 2023 5
拡張 (1) ファイル直書き方式 - 2拡張 (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;
Apr 10, 2023 6
拡張 (2) inc にあるテンプレ読み込み方式 - 1拡張 (2) inc にあるテンプレ読み込み方式 - 1
inc パスに通したテンプレから include use lib で適当なディレクトリにパスを通
すと、そこにあるファイルを対応するモジュールの拡張領域に差し込んでくれる機能 ここで注意しないとダメなのは Schema クラ
スは対象外 Table クラスのみ拡張可能 ちなみに拡張領域の箇所はファイル直書き方
式と同じ
Apr 10, 2023 7
拡張 (2) inc にあるテンプレ読み込み方式 - 2拡張 (2) inc にあるテンプレ読み込み方式 - 2
ディレクトリ構成lib
MyApp
DBIC
Schema
User.pm
schema
MyApp
DBIC
Schema
User.pm
自動生成される領域
Include(ファイルの下部にくっつく )
Apr 10, 2023 8
make_schema_at() [2]make_schema_at() [2]
really_erase_files ( 生成オプション ) true の時
毎回ファイルを消して生成する Schema, Table クラス両方消しちゃうので、
ファイル直書き方式は使えない>< 必然的に include になるが、 Schema に対しては
適用出来ない false の時
毎回ファイルを消さない 直書き方式が使える
但し消さないと include で挿入されたブロックが次回の直書きと見なされ、再び include されるので重複コードになるwww
Apr 10, 2023 9
ここまでのまとめここまでのまとめ
現在の問題点 Schema, Table 共に後付的に拡張したい
Schema も対象にするなら really_erase_filesを false にする
そうすると直書き領域に make_schema_at する度に重複するコードが出来てしまう
どうすれば良いか really_erase_files => 0 でも自分で Table クラスを消せば同じ事にな
る 拡張は Schema は直書き、 Table は include
でやる。
Apr 10, 2023 10
改良版 Schema 生成改良版 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);
Apr 10, 2023 11
さらなる改良さらなる改良
Schema::Loader について 中で何やってるか理解すればもっとカス
タマイズ出来そう 特にリレーションとか通常の使い方では手出
しできない部分を何とかしたい まずはクラス図から
Apr 10, 2023 12
Class::Diagram of DBIC::Schema::LoaderClass::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 時のオプションの詳細
Apr 10, 2023 13
RelationShip [1]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 自然になる こうしたい
Apr 10, 2023 14
RelationShip [2]RelationShip [2]
問題の箇所 DBIC::Schema::Loader::Base の _load_relat
ionship()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 の引数リスト ); }}
Apr 10, 2023 15
RelationShip [4]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} } ); }}
Apr 10, 2023 16
まとめまとめ
Schema::Loader との付き合いかた really_erase_files を false
でも自分で Table 消す Schema は直書き、 Table は include で辻褄合わせる belongs_to は問題箇所を redifine する
名前でコード生成時の制約をつけるのは良さそう。 on_created, on_updated(DATETIME) で NOW() 相当とか
時間の都合上割愛したけど、それ以上は自分で DBIC流儀のプラグイン書く ( 割と便利 )
そこまでするなら自分で Loader 書くべき?(ぇ あるいは DBIC を使わない
Apr 10, 2023 17
おしまいおしまい
ご清聴ありがとうございました