Dealing with a STRANGE API

Discussion in 'Perl Misc' started by Ignoramus7272, Oct 6, 2006.

  1. I am using PayPal API class

    Business::payPal::API::TransactionSearch

    It uses some very weird code

    my %response = ();
    unless( $self->getBasic($som, $path, \%response) ) {
    $self->getErrors($som, $path, \%response);
    return %response;
    }

    return $self->getFieldsList( $som, $path . '/PaymentTransactions',
    { Timestamp => 'Timestamp',
    Timezone => 'Timezone',
    Type => 'Type',
    Payer => 'Payer',
    PayerDisplayName => 'PayerDisplayName',
    TransactionID => 'TransactionID',
    Status => 'Status',
    GrossAmount => 'GrossAmount',
    FeeAmount => 'FeeAmount',
    NetAmount => 'NetAmount',
    } );

    that is, it returns a hash when there is error, and a list reference when there is not.

    I am bewildered, just how can I get this result into one variable and
    then figure out if I am dealing with success (so that I can print
    results from the list reference), or failure (so that I can print a
    hash element error message).

    Any idea? I tried obvious things like setting a scalar to the result
    of this function, and could not.

    The man pages gloss over this issue. I did read them in their entirety.

    i
     
    Ignoramus7272, Oct 6, 2006
    #1
    1. Advertising

  2. Ignoramus7272

    -berlin.de Guest

    Ignoramus7272 <ignoramus7272@NOSPAM.7272.invalid> wrote in comp.lang.perl.misc:
    > I am using PayPal API class
    >
    > Business::payPal::API::TransactionSearch
    >
    > It uses some very weird code


    Indeed. Snipped.

    > that is, it returns a hash when there is error, and a list reference
    > when there is not.
    >
    > I am bewildered, just how can I get this result into one variable and
    > then figure out if I am dealing with success (so that I can print
    > results from the list reference), or failure (so that I can print a
    > hash element error message).
    >
    > Any idea? I tried obvious things like setting a scalar to the result
    > of this function, and could not.


    Untested:

    my @mystery = $obj->meth_from_hell( ...);

    if ( @mystery == 1 ) {
    my @array = @{ $mystery[ 0] };
    # normal processing
    } else {
    my %hash = @mystery;
    # error
    }

    The distinction is reliable because the hash returns an even number of
    scalars.

    You shouldn't have to do this.

    Anno
     
    -berlin.de, Oct 7, 2006
    #2
    1. Advertising

  3. Ignoramus7272

    Ben Morrow Guest

    Quoth Ignoramus7272 <ignoramus7272@NOSPAM.7272.invalid>:
    > On 6 Oct 2006 23:12:19 GMT, -berlin.de
    > <-berlin.de> wrote:
    > > Ignoramus7272 <ignoramus7272@NOSPAM.7272.invalid> wrote in comp.lang.perl.misc:
    > >> I am using PayPal API class
    > >>
    > >> Business::payPal::API::TransactionSearch

    > >
    > > Untested:

    [snipped]
    >
    > OK, thanks. I used your code to write this:
    >
    > sub run_weird_method {
    > my ($sub, @args) = @_;
    > my @mystery = &$sub( @args );


    I don't know if you realise, but this will not call $sub as a method.
    (Even if you pass in an object as the first argument manually, you will
    not get any inheritance). You would have to call this function as

    my %results = run_weird_method
    sub { $PayPal->TransactionSearch(@_) },
    qw/foo bar baz/;

    which is a little odd, to say the least. For my part, if I really wanted
    a general-purpose sub like this (AFAICT, this is the only sub in
    Business::payPal that behaves like this, so I'd probably just wrap
    that), I would either prototype it to accept a coderef and call that:

    sub call_weird (&) {
    my ($sub) = @_;
    my @mystery = $sub->();
    ...
    }

    my $results = call_weird {
    $PayPay->TransactionSearch(qw/foo bar baz/);
    };

    or simply accept and translate a list:

    sub remove_weirdness {
    my @mystery = @_;
    ...
    }

    my $results = remove_weirdness
    $PayPal->TransactionSearch(qw/foo bar baz/);

    If you really want to pass a method and an arglist you would need to
    accept an object argument as well:

    sub run_weird_method {
    my ($obj, $meth, @args) = @_;
    my @mystery = $obj->$meth(@args);
    ...
    }

    my $results = run_weird_method
    $PayPal, TransactionSearch => qw/foo bar baz/;

    A quick scan of the docs for B::pP::A::TS suggests that this behaviour is
    a bug. Indeed, both the initial example and the "ERROR HANDLING" section
    state that a succesful return *also* returns a hash, with a true 'Ack'
    member and the result somewhere else (unspecified) in the hash. The 0.11
    version says the module is still in alpha: Be Very Careful. Alpha
    modules playing with your money is not something I would like. Depending
    on how much work you want to do, you may be better off calling the
    PayPal API yourself with SOAP::Lite.

    > if ( @mystery == 1 ) {
    > # normal processing
    > return { success => 1, result => $mystery[0] };
    > }
    >
    > # Failure
    > my %hash = @mystery;
    > return { success => 0, result => \%hash };


    Here I would instead emulate the rest of the B::pP::A interface, that is

    if (@mystery == 1) {
    # success
    return ( Ack => 'Success', Results => $mystery[0] );
    }
    else {
    # failure

    # the hash should already have an Ack => 'Failure' member
    return @mystery;

    # if for some reason it doesn't:
    # return ( Ack => 'Failure', @mystery );
    }

    Not that I like that interface one bit, but consistency is always a good
    thing :).

    I would also consider overwriting &B::pP::A::TS::TransactionSearch with
    a sub that behaves correctly (perhaps with Hook::LexWrap); and
    submitting a patch to the author.

    Ben

    --
    If I were a butterfly I'd live for a day, / I would be free, just blowing away.
    This cruel country has driven me down / Teased me and lied, teased me and lied.
    I've only sad stories to tell to this town: / My dreams have withered and died.
    (Kate Rusby)
     
    Ben Morrow, Oct 7, 2006
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Shlomo Anglister
    Replies:
    1
    Views:
    409
    Default User
    Aug 2, 2004
  2. Praveen, Tayal (IE10)
    Replies:
    0
    Views:
    378
    Praveen, Tayal (IE10)
    Mar 17, 2005
  3. John123

    Profiling API or Membership API

    John123, Oct 20, 2006, in forum: ASP .Net
    Replies:
    0
    Views:
    375
    John123
    Oct 20, 2006
  4. Josh Huber
    Replies:
    1
    Views:
    89
    Friedrich Dominicus
    Apr 10, 2004
  5. Replies:
    3
    Views:
    278
Loading...

Share This Page