Customization of DBIC::Schema::Loader
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Customization of DBIC::Schema::Loader

on

  • 3,360 views

 

Statistics

Views

Total Views
3,360
Views on SlideShare
3,357
Embed Views
3

Actions

Likes
0
Downloads
10
Comments
0

2 Embeds 3

http://www.slideee.com 2
http://www.slideshare.net 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Customization of DBIC::Schema::Loader Presentation Transcript

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