2009年05月28日

「全裸は違法だということを言われた。ええええ、そんな法律があるのか?Debugはできるようになるかもしれない。」と思っておセンチなyappoです。

hashを簡単にmergeするCPAN moduleとしてHash::Mergeがあるのは有名ですが、デフォルトだと色々頑張ってマージしちゃうので、例えばHTTP::Engine::Middlewareの使いたいMiddlewareをARRAY refで書いちゃったりして、base.yamlとproduction.yamlでmergeした時に、以下のような混ざりかたでとんでも無い目にあいます。

use strict;
use warnings;
use YAML;
use Hash::Merge;

my $base = {
    Middlewares  => [
        { module => 'HTTPSession', config => { name => '開発やらステージング用の設定だよ' } },
        { module => 'MethodOverride' }, # 全部で共通して使いたいよ
    ],
    name => 'base',
    base => 1,
};

my $production = {
    Middlewares  => [
        { module => 'HTTPSession', config => { name => '本番用の設定だよ' } },
    ],
    name => 'production',
    production => 1,
};

my $config = Hash::Merge::merge($base, $production);
print Dump($config);
---
Middlewares:
  - config:
      name: 開発やらステージング用の設定だよ
    module: HTTPSession
  - module: MethodOverride
  - config:
      name: 本番用の設定だよ
    module: HTTPSession
base: 1
name: base
production: 1

これは、マズいですね、HTTPSessionの設定を開発と本番で別けたいのにARRAYだから全部混ざっちゃいます。

そんな時はspecify_behaviorでmergeのルールを弄れるのです。左のreftype => 右のreftypeみたいな形で、左の要素がSCALARで右の要素がARRAYだったどうこうするみたいな事が出来ます。
ぶっちゃけ左の要素がHASHで右の要素がARRAYとかだいぶあり得ないので、そういった組み合わせになったらdieするとかすると混乱無いと思います。

こんかいは左右でreftypeが違うと混乱するし、ARRAY同士でmergeしないで右要素だけを生かしたいと言う要望でbehaviorを作ったです。あと、behavior作っちゃうとデフォルトの振る舞いが上書きされるのでget_behaviorで今の振る舞いを取っておいて用が済んだらset_behaviorすると良いと思います。

use strict;
use warnings;
use YAML;

use Carp;
use Hash::Merge;

my $base = {
    Middlewares  => [
        { module => 'HTTPSession', config => { name => '開発やらステージング用の設定だよ' } },
        { module => 'MethodOverride' }, # 全部で共通して使いたいよ
    ],
    name => 'base',
    base => 1,
};

my $production = {
    Middlewares  => [
        { module => 'HTTPSession', config => { name => '本番用の設定だよ' } },
        { module => 'MethodOverride' }, # array は上書きされるので、こっちにもかく
    ],
    name => 'production',
    production => 1,
};

my $old_behavior =  Hash::Merge::get_behavior;
Hash::Merge::specify_behavior({
    SCALAR => {
        SCALAR => sub { $_[1] },
        ARRAY  => sub { Carp::croak 'SCALAR and ARRAY cannot merge in config file.' },
        HASH   => sub { Carp::croak 'SCALAR and HASH cannot merge in config file.' },
    },
    ARRAY  => {
        SCALAR => sub { Carp::croak 'ARRAY and SCALAR cannot merge in config file.' },
        ARRAY  => sub { $_[1] },
        HASH   => sub { Carp::croak 'ARRAY and HASH cannot merge in config file.' },
    },
    HASH   => {
        SCALAR => sub { Carp::croak 'HASH and SCALAR cannot merge in config file.' },
        ARRAY  => sub { Carp::croak 'HASH and ARRAY cannot merge in config file.' },
        HASH   => sub { Hash::Merge::_merge_hashes( $_[0], $_[1] ) },
    },
}, 'MY_CONFIG_STRICT_MODE' );

my $config = Hash::Merge::merge($base, $production);
Hash::Merge::set_behavior( $old_behavior );

print Dump($config);
---
Middlewares:
  - config:
      name: 本番用の設定だよ
    module: HTTPSession
  - module: MethodOverride
base: 1
name: production
production: 1
素敵にマージされましたね。

Posted by Yappo at 2009年05月28日 15:26 | TrackBack | Perl
Comments

rs gold | RS money | buy rs money | buy rs gold | cheap rs gold | cheap rs money | Runescape gold | Runescape money | Runescape power leveling | Runescape powerleveling | rs power leveling | rs powerleveling | rs accounts | rs account | runescape accounts | runescape account | rs powerleveling | Runescape powerleveling | rs power leveling | Runescape power leveling | Runescape gold|Runescape Money | Runescape gold|Runescape Money | rs gold|rs Moneyrs gold | RS money | buy rs money | buy rs gold | cheap rs gold | cheap rs money | Runescape gold | Runescape money | Runescape power leveling | Runescape powerleveling | rs power leveling | rs powerleveling | rs accounts | rs account | runescape accounts | runescape account | rs powerleveling | Runescape powerleveling | rs power leveling | Runescape power leveling | Runescape gold|Runescape Money | Runescape gold|Runescape Money | rs gold|rs Moneyrs gold | RS money | buy rs money | buy rs gold | cheap rs gold | cheap rs money | Runescape gold | Runescape money | Runescape power leveling | Runescape powerleveling | rs power leveling | rs powerleveling | rs accounts | rs account | runescape accounts | runescape account | rs powerleveling | Runescape powerleveling | rs power leveling | Runescape power leveling | Runescape gold|Runescape Money | Runescape gold|Runescape Money | rs gold|rs Moneyrs gold | RS money | buy rs money | buy rs gold | cheap rs gold | cheap rs money | Runescape gold | Runescape money | Runescape power leveling | Runescape powerleveling | rs power leveling | rs powerleveling | rs accounts | rs account | runescape accounts | runescape account | rs powerleveling | Runescape powerleveling | rs power leveling | Runescape power leveling | Runescape gold|Runescape Money | Runescape gold|Runescape Money | rs gold|rs Moneyrs gold | RS money | buy rs money | buy rs gold | cheap rs gold | cheap rs money | Runescape gold | Runescape money | Runescape power leveling | Runescape powerleveling | rs power leveling | rs powerleveling | rs accounts | rs account | runescape accounts | runescape account | rs powerleveling | Runescape powerleveling | rs power leveling | Runescape power leveling | Runescape gold|Runescape Money | Runescape gold|Runescape Money | rs gold|rs Money

Posted by: Runescpae power leveling at 2009年06月23日 15:47
Post a comment









Remember personal info?






コメントを投稿する前に↓の場所にnospamと入力してください。