in reply to Given a tie object, get a tied hash (or scalar, or whatever)

Why not alter your classes TIEHASH to take an optional object-to-use argument so you could then do:

tie(%newhash, 'My::Hash::Tie::Class', using => $obj, @args);

Sound sane?

Replies are listed 'Best First'.
Re: Re: Given a tie object, get a tied hash (or scalar, or whatever)
by Dice (Beadle) on Aug 13, 2003 at 15:22 UTC
    Hmm... it's an idea. But really, I'm not going to be using My::Hash::Tie::Class. I'll be working with Apache::Session or Apache::SessionX. (That was meant to be a metasyntactic class name variable.)

    I could end up subclassing either to My::ApacheSessionRipOff and implement things this way I suppose, but hopefully that will be my second option on how to proceed, and not my only one.

    Cheers,
    Richard

      Can you explain what you're trying to do with Apache::Session? There might be another way.
        I fear that giving the complete answer to this quesiton will only show the kind of deludged curmudgeon I am.

        So I'm working on a web project. I'm working with CGI::Application. I want to use Apache::Session (or SessionX, whatever) to do my sessioning stuff. I want to retrieve my session in the setup stage, and then just haul its ass around to whatever run-modes I need via the $self.

        Now, $self->param within CGI::Application could do the job, a la:

        sub setup { my $self = shift; tie %session, 'Apache::Session', $self->query->cookie('session_id' +); $self->param('session', \%session); # etc. } sub current_run_mode { my $self = shift; # etc. my $uid = $self->param('session')->{uid}; # etc. }

        I'm willing to do this, if need be. But I like my composited objects (and their related methods) to be "first class". In this case, that means I'd rather my attempts to get session data would look like:

        my $uid = $self->session->uid;

        How would I do this? (Rhetorical question.) I have already subclassed CGI::Application to My::CGIApplication that gives me 1st class object composition capabilities, like this:

        sub setup { my $self = shift; tie %session, 'Apache::Session', $self->query->cookie('session_id' +); $self->composite_object( name => 'session', object => tied(%session)); # etc. }

        This gives me calls like $self->session. So now I need to get at the session data in a first class way. (Obviously I could get at it in a 2nd or 3rd class way such as $self->session->FETCH('uid'), but I don't like the smell of this.)

        So, this leads me to subclassing Apache::Session. Consider My::ApacheSession which has within it this...

        sub AUTOLOAD { my $self = shift; my $attribute = $AUTOLOAD; $method =~ s/.*:://; if ( length($method) != 0 ) { if ( @_ > 1) { return $self->STORE($attribute, @_); } else { return $self->FETCH($attribute); } } else { croak "No such object attribute referenced by name '" . $attribute . ' to provide "; } }
        So this is entirely doable. However, I would like it cleaner (i.e. forgetting about FETCH and STORE). So refer back to my original posting...
        sub AUTOLOAD { my $self = shift; my $attribute = $AUTOLOAD; $method =~ s/.*:://; my %session = Foo($self); if ( @_ > 1) { return $session{$attribute} = $_[0]; } else { return $session{$attribute}; } }
        So that's all. Hope with all that wind-up it wasn't an anticlimax. Perrin, as you said, there is another way. I was just hoping that the way I wanted to do things exists, too.

        Cheers,
        Richard

      But really, I'm not going to be using My::Hash::Tie::Class. I'll be working with Apache::Session or Apache::SessionX. (That was meant to be a metasyntactic class name variable.)

      Ah. In that case something like this will probably do the trick (untested code):

      package Tie::WrapUsing; sub TIEHASH { my ($class, $object) = @_; return $object; }; package main; use Test::More tests => 2; use Apache::Session::File; my $object = tie my %orig, 'Apache::Session::File', undef, { Directory => '/tmp' }; tie my %dupe, 'Tie::WrapUsing', $object; $orig{foo}=42; $dupe{bar}=24; is $dupe{foo}, 42, 'change in original reflected in duplicate'; is $orig{bar}, 24, 'change in duplicate reflected in original';

      However, your real problem seems to be that you want to use a tied hash as an object - which kind of defeats the purpose :-) If I were you I'd use an object-based session system like Cache::Cache instead.