パルカワ2

PerlとRubyとイチャラブ

package Result::User {
    use strict;
    use warnings;
    use utf8;

    sub new { bless {}, shift }

    sub to_model {
        my $self = shift;
        Model::User->new(user => $self);
    }
};

package Model::User {
    use strict;
    use warnings;
    use utf8;
    use Mouse;

    has user => (
        is => "rw",
        isa => "Result::User",
        required => 1,
    );

    has guild_model => (
        is => "rw",
        isa => "Model::User::Guild",
        default => sub {
            my $self = shift;
            Model::User::Guild->new(user_model => $self);
        },
        lazy => 1,
    );

    no Mouse;
};

package Model::User::Guild {
    use strict;
    use warnings;
    use utf8;
    use Mouse;
    use Data::Dumper;

    has user_model => (
        is => "rw",
        isa => "Model::User",
        required => 1,
        weak_ref => 1,
    );

    no Mouse;

    sub join {
        my $self = shift;

        my $user = Result::User->new;

        {
            # guild_modelのuser_modelには、ちゃんとModel::Userのオブジェクトが入っている
            warn Dumper $user->to_model->guild_model;
            # $VAR1 = bless( {
            #         'user_model' => bless( {
            #                 'guild_model' => $VAR1,
            #                 'user' => bless( {}, 'Result::User' )
            #             }, 'Model::User' )
            #     }, 'Model::User::Guild' );
        };

        {
            # 変数にいれるとguild_modelのuser_modelがundefになる。
            my $guild_model = $user->to_model->guild_model;
            warn Dumper $guild_model;
            # $VAR1 = bless( {
            #         'user_model' => undef
            #     }, 'Model::User::Guild' );
        };

        {
            # user_modelを一旦変数に落とすと正常になる
            my $user_model  = $user->to_model;
            my $guild_model = $user_model->guild_model;
            warn Dumper $guild_model;
            # $VAR1 = bless( {
            #         'user_model' => bless( {
            #                 'guild_model' => $VAR1,
            #                 'user' => bless( {}, 'Result::User' )
            #             }, 'Model::User' )
            #     }, 'Model::User::Guild' );
        };
    }
};

Result::User->new->to_model->guild_model->join;
# 疑問篇
acidlemon | Resultを作り直している意図がよくわからなくてそういうのを避けた方がいいんじゃないってコメントしたい感じになってるけど
acidlemon | なんか別のRowから取ってきてるから別のResultなんです! みたいなのを想定すればいいのかな
 hisaichi | そういうことなんです > 別のRowから取ってきてるから別のResultなんです!
acidlemon | 了解了解

# 解答篇
acidlemon | まぁweakrefだしそんなもんじゃないかなあ
       -- | Notice(acidlemon):             # 変数にいれるとguild_modelのuser_modelがundefになる。
       -- | Notice(acidlemon):             my $guild_model = $user->to_model->guild_model;
acidlemon | ここが
acidlemon | to_modelでModel::Userをto_model内につくってるけど
acidlemon | to_model抜けたら作ったオブジェクトがスコープ抜けてリファレンスカウント落ちるから
acidlemon | User::Guildがweakrefでuserをもつようになってると
acidlemon | そっちのリファレンスカウントが上がらないので
acidlemon | リファレンスカウントが0になってそのまま解放される
acidlemon | $guild_modelに入れて受けて、次の行に進んだ時点で解放されてるとおもう
   soh335 | そんなかんじっぽい
 hisaichi | そんな感じっぽい...

# 解決篇
 acidlemon | ResultがModel::User持てば良いんですよ
 acidlemon | to_modelde
 acidlemon | undefだったら作って返すけど持ってたらそのまま返す
 acidlemon | Resultが破棄されるタイミングでModelも一緒に破棄される