kbrandt has asked for the wisdom of the Perl Monks concerning the following question:

Hi All, I am trying to build my first module using method maker. Right now I have to classes, UPS::TrackRequest and UPS::TrackedPackage. When I Try to have a subroutine of TrackRequest pass a hash to TrackedPackage I don't get what I expect. print Dumper($processedXML); within the TrackRequest object has what I expect, but print Dumper($Package->_returned_xml()); in mny test script doesn't.
package UPS::TrackRequest; use strict; use warnings; use LWP::UserAgent; use HTTP::Request::Common; use XML::Simple; use Data::Dumper; use UPS::TrackedPackage; use Class::MethodMaker [ new => "new", scalar => [ qw( License Username Password TrackingNumber _returned +_xml debug) ], scalar => [ [{ -default => 'https://wwwcie.ups.com/ups.app/xml/Tra +ck' }, 'URL'], [{ -default => 'A Package'}, 'description'] ] ]; sub requestTrack { my $self = shift; my $_ups_xml_req = " <?xml version=\"1.0\" ?> <AccessRequest xml:lang='en-US'> <AccessLicenseNumber>$self->License</AccessLicenseNumber> <UserId>$self->UserName</UserId> <Password>$self->Password</Password> </AccessRequest> <?xml version=\"1.0\" ?> <TrackRequest> <Request> <TransactionReference> <CustomerContext>$self->PackageName</CustomerConte +xt> </TransactionReference> <RequestAction>Track</RequestAction> <RequestOption>activity</RequestOption> </Request> <TrackingNumber>$self->TrackingNumber</TrackingNumber> </TrackRequest> "; if (defined( $self->debug) ) { print $_ups_xml_req, "\n"; } my $userAgent = LWP::UserAgent->new(agent => 'perl post'); my $response = $userAgent->request(POST $self->URL, Content_Type = +> 'text/xml', Content => $_ups_ +xml_req); if (defined( $self->debug) ) { print $response->decoded_content, " +\n"; } print $response->error_as_HTML unless $response->is_success; my $xml = new XML::Simple; #$self->{_returned_xml} = $xml->XMLin( $response->decoded_content) +; my $processedXML = $xml->XMLin( $response->decoded_content); #print Dumper($processedXML); #print $processedXML->{Response}{Error}{ErrorDescription}; #return UPS::TrackedPackage->new( _returned_xml => $processedXML); print (%{$processedXML}); return UPS::TrackedPackage->new( _returned_xml => %{$processedXML} +); } #sub { 1; use strict; use warnings; package UPS::TrackedPackage; use Class::MethodMaker [ new => "new", scalar => 'debug' , hash => '_returned_xml' , ]; 1; #########My Test Script###########: use strict; use warnings; use UPS::TrackRequest; use Data::Dumper; my $Package = UPS::TrackRequest->new(); $Package->Username('miles800'); #print $Package->Username(); #print $Package->URL(); my $tp = $Package->requestTrack(); print $Package->_returned_xml(); print $tp; print Dumper($Package->_returned_xml()); #print $tp->_returned_xml()->{Shipment}{Shipper}{Address};

Replies are listed 'Best First'.
Re: Passing a Hash to another Object in MethodMaker
by kennethk (Abbot) on Mar 10, 2009 at 18:47 UTC

    Disclaimer: I have never used Class::MethodMaker and think the documentation needs some copy editing, particularly as the documents for hash functionality are all dead links.

    In Class::Method::array, where the array functionality is discussed, the array invocation is done through array references not arrays (i.e. array => [qw/ x /]). This implies to me that your issue is that you are passing it a hash (which would be an very poorly scaling interface indeed) in place of a hash ref. What happened when you tried that (I note a corresponding line in your source is commented out)?

    Update: Found Class::Method::hash through some linking. From *_set, it appears that you are invoking it improperly. Have you tried

    my $object = UPS::TrackedPackage->new; $object->_returned_xml_set( %{$processedXML} ); return $object;

    Update 2: Fixed a bad link.

      Hi Kenneth, It does seem right that I was calling it incorrectly. The above still doesn't give me what I am after ... If I change
      use Class::MethodMaker [ new => "new", scalar => 'debug' , hash => '_returned_xml' , ];
      to
      use Class::MethodMaker [ new => "new", scalar => 'debug' , scalar => '_returned_xml' , ];
      and then...
      my $object = UPS::TrackedPackage->new; return $object->_returned_xml('foo'); #The set seems out of date
      and with: :
      my $tp = $Package->requestTrack(); #print $Package->_returned_xml(); print $tp->_returned_xml(); print Dumper($Package->_returned_xml());
      I get: Can't locate object method "_returned_xml" via package "foo" (perhaps you forgot to load "foo"?) at ootrack.pl line 32. It seems there may be something I am just not getting:-) Perhaps I might have better luck with a different OO library?
        There are a number of very popular OO frameworks (Moose, Mouse, Class::Struct, ...). Fixing what you have here, though, should be straight forward - from Class::Method::hash:
        If a single argument is provided that is an arrayref or hashref, it is expanded and its contents used in place of the existing contents
        In other words, replace 'foo' in your code with $processedXML, you'll pass the hash and all will be well. Unless, of course, the documentation is lying.