Customization of DBIC::Schema::Loader

17
catalyst conference #1 Customization DBIC::Schema::Loade r d:id:ZIGOROu Toru Yamaguchi <[email protected]>

description

 

Transcript of Customization of DBIC::Schema::Loader

Page 1: Customization of DBIC::Schema::Loader

catalyst conference #1

Customization DBIC::Schema::Loader

Customization DBIC::Schema::Loader

d:id:ZIGOROu

Toru Yamaguchi <[email protected]>

Page 2: Customization of DBIC::Schema::Loader

Apr 10, 2023 2

AgendaAgenda

DBIC::Schema::Loader のおさらい make_schema_at()

生成されたファイル自体に拡張 inc パスの追加による拡張 really_erase_files の値 Schema クラスも拡張対象にする

DBIC::Schema::Loader を改造 DBIC::Schema::Loader の概要 名前に制約をつけてリレーション設定

まとめ

Page 3: Customization of 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'], );

Page 4: Customization of DBIC::Schema::Loader

Apr 10, 2023 4

拡張 (1) ファイル直書き方式 - 1拡張 (1) ファイル直書き方式 - 1

生成されたファイルに拡張 生成された Schema, Table クラスそれぞ

れの下の方に “ DO NOT MODIFY THIS” と書かれたコメントがある そこから “ You can replace this text” の領域

は拡張領域で自動生成の対象ではない 生成されたファイルに直接書いて良い

追加で load_components() したりとか あるいは他のプラグインのメソッド叩いたり テーブル定義をゴニョゴニョしたりとか

Page 5: Customization of DBIC::Schema::Loader

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;

Page 6: Customization of DBIC::Schema::Loader

Apr 10, 2023 6

拡張 (2) inc にあるテンプレ読み込み方式 - 1拡張 (2) inc にあるテンプレ読み込み方式 - 1

inc パスに通したテンプレから include use lib で適当なディレクトリにパスを通

すと、そこにあるファイルを対応するモジュールの拡張領域に差し込んでくれる機能 ここで注意しないとダメなのは Schema クラ

スは対象外 Table クラスのみ拡張可能 ちなみに拡張領域の箇所はファイル直書き方

式と同じ

Page 7: Customization of DBIC::Schema::Loader

Apr 10, 2023 7

拡張 (2) inc にあるテンプレ読み込み方式 - 2拡張 (2) inc にあるテンプレ読み込み方式 - 2

ディレクトリ構成lib

MyApp

DBIC

Schema

User.pm

schema

MyApp

DBIC

Schema

User.pm

自動生成される領域

Include(ファイルの下部にくっつく )

Page 8: Customization of DBIC::Schema::Loader

Apr 10, 2023 8

make_schema_at() [2]make_schema_at() [2]

really_erase_files ( 生成オプション ) true の時

毎回ファイルを消して生成する Schema, Table クラス両方消しちゃうので、

ファイル直書き方式は使えない>< 必然的に include になるが、 Schema に対しては

適用出来ない false の時

毎回ファイルを消さない 直書き方式が使える

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

Page 9: Customization of DBIC::Schema::Loader

Apr 10, 2023 9

ここまでのまとめここまでのまとめ

現在の問題点 Schema, Table 共に後付的に拡張したい

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

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

どうすれば良いか really_erase_files => 0 でも自分で Table クラスを消せば同じ事にな

る 拡張は Schema は直書き、 Table は include

でやる。

Page 10: Customization of DBIC::Schema::Loader

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);

Page 11: Customization of DBIC::Schema::Loader

Apr 10, 2023 11

さらなる改良さらなる改良

Schema::Loader について 中で何やってるか理解すればもっとカス

タマイズ出来そう 特にリレーションとか通常の使い方では手出

しできない部分を何とかしたい まずはクラス図から

Page 12: Customization of DBIC::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 時のオプションの詳細

Page 13: Customization of DBIC::Schema::Loader

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 自然になる こうしたい

Page 14: Customization of DBIC::Schema::Loader

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 の引数リスト ); }}

Page 15: Customization of DBIC::Schema::Loader

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} } ); }}

Page 16: Customization of DBIC::Schema::Loader

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 を使わない

Page 17: Customization of DBIC::Schema::Loader

Apr 10, 2023 17

おしまいおしまい

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