Markdown-Pod

 view release on metacpan or  search on metacpan

t/mkd/2011-12-17.mkd  view on Meta::CPAN

    #!perl
    package MyApp::Schema::ResultBase;
    use Moose;
    use MooseX::NonMoose;
    use namespace::autoclean;
    extends 'DBIx::Class::Core';

    sub my_method {};

    __PACKAGE__->meta->make_immutable;

    1;

그리고 결과 클래스에서 이 `ResultBase`를 상속합니다.

    #!perl
    package MyApp::Schema::Result::Access;
    ....
    - extends 'DBIx::Class::Core';
    + extends 'MyApp::Schema::ResultBase';
    ....

어, 그런데 뭔가 걸립니다.

    #!perl
    # DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:8E8XDlgZJWsPmqTw/xP34A

맙소사! `ResultBase`를 상속하는 것조차도 이 문구위에 놓이게 되니 맘편히 고칠수도 없네요!


스키마 클래스 덤프에 설정파일을 사용
-----------------------------------

위에서 스키마 클래스를 덤프할 때 기나긴 옵션이 붙은 커맨드가 있었습니다.
데이터베이스 구성이 바뀌어질 때마다 그 긴 커맨드를
일일이 붙여넣기 식으로 넣어야하니, 좋은 방법 같지는 않습니다.
우선 *기존 명령*의 사용을 그만두도록 합니다.
컴포넌트 등록이나, `ResultBase` 클래스 설정이나 컬럼의 속성 추가 등등
매번 스키마 클래스 덤프할 때마다 자신의 상황에 맞게
이것저것 개조(customize)할 필요가 있습니다.

아쉽게도 *기존 명령*으로 호출되는 [Catalyst::Model::DBIC::Schema][cpan-cmds] 모듈에 속해있는
[Catalyst::Helper::Model::DBIC::Schema][cpan-chmds]로는 현재 상황을 헤쳐 나가기 힘듭니다.
그래서 위 모듈 안에서 본질적으로 스키마 클래스 덤프에 사용되는 모듈인
[DBIx::Class::Schema::Loader][cpan-dbic-schema-loader]를 사용합니다.
[DBIx::Class::Schema::Loader][cpan-dbic-schema-loader]가 설치되어 있으면
`dbicdump`라는 명령이 존재할 것입니다.
이 `dbicdump` 커맨드에 이제부터 이 상황을 타개할 설정 파일을 담겠습니다.
설정 파일은 [Config::Any][cpan-config-any] 모듈로 처리되므로
펄에서 쓰이는 어떤 형식이라도 다룰 수 있습니다.
심지어는 *펄 코드* 자신도 설정으로 사용할 수 있습니다.
아래는 `dbicdump` 설정 파일의  예제입니다.

    #!perl
    {
        schema_class => "MyApp::Schema",
        connect_info => {
            dsn  => $ENV{DB_DSN}      || "dbi:mysql:test_db:127.0.0.1",
            user => $ENV{DB_USER}     || "test_user",
            pass => $ENV{DB_PASSWORD} || "test_password",
            mysql_enable_utf8  => 1,
        },
        loader_options => {
            dump_directory     => 'lib',
            naming             => { ALL => 'v8' },
            skip_load_external => 1,
            relationships      => 1,

            use_moose          => 1,
            only_autoclean     => 1,

            col_collision_map  => 'column_%s',
            result_base_class => 'MyApp::Schema::ResultBase',
            overwrite_modifications => 1,
            datetime_undef_if_invalid => 1,
        
            custom_column_info => sub {
                my ($table, $col_name, $col_info) = @_;

                if ($col_name eq 'created_on') {
                    return { %{ $col_info }, set_on_create => 1 };
                }
            },
        },
    }

항목들이 많으므로 전부 설명하는 대신, 위에서 봉착했던 문제에 대해 추려볼까요?
우선 `ResultBase` 클래스 문제입니다. `result_base_class` 값을 지정해 줌으로써
모든 결과클래스들은 `DBIx::Class::Core`가 아니라 `MyApp::Schema::ResultBase`를
상속받게 됩니다. 물론 `MyApp::Schema::ResultBase`는 스스로 정의해줘야 합니다.
다음은 컬럼의 컴포넌트를 이용한 확장 문제입니다.
MD5 체크섬 값 아래에 중복되는 코드를 매번 적어주어야 했습니다.
이렇게 사용할 컴포넌트들을 결과클래스 별로 지정하는 대신 `ResultBase` 클래스를 읽어들입니다.
사실 이처럼 `ResultBase`를 놓고 여기에 컴포넌트를 일괄해서 읽어들이는 방식은
Cookbook 문서에서도 [스타트업 속도 향상을 위해 권장][dbic-cookbook-speed]하고 있습니다.


    #!perl
    package MyApp::Schema::ResultBase;
    use Moose;
    use MooseX::NonMoose;
    use namespace::autoclean;
    extends 'DBIx::Class::Core';

    __PACKAGE__->load_components(qw/
      InflateColumn::DateTime
      TimeStamp
      ...
    /);

    __PACKAGE__->meta->make_immutable;

    1;

그리고 컴포넌트의 사용을 위한 컬럼의 속성은
`custom_column_info` 속성에 코드를 등록해 지정할 수 있습니다.
위의 코드처럼 등록하면 `created_on`에 `TimeStamp` 컴포넌트를 사용하기 위한
속성 값인 `set_on_create`이 모든 결과클래스에 추가됩니다.


설정파일을 이용한 스키마 덤프



( run in 1.982 second using v1.01-cache-2.11-cpan-39bf76dae61 )