Perl one liner to display module version info

I use this Perl one-liner to display the version number of a module. This module should be available in your @INC paths.

If I need to know the version of CGI.pm

$ perl -MCGI -e ‘print “$CGI::VERSION\n”‘
3.29

I created a shell script so that I can just type the module name.

$ cat pm_version.sh
#!/bin/sh
MODULE=$1
perl -M$MODULE -e ‘print “$’$MODULE’::VERSION\n”‘

So now, I can do this.

$ pm_version.sh Google::Adwords
v1.13

Using Test::Deep to test list of objects

What would you do if you wanted to test (using Test::More) whether a certain method call returns a list of objects?

Maybe use a while loop and test each element with an isa_ok($_ , ‘Object’)

But that would just increase the number of tests and if the method call returns an unknown number of objects then you won’t know in advance how many tests are to be run.

Another option is to cycle through the list and check each element using a if (ref($_) eq “Object”) and use a count variable to keep track of the number of objects. At the end of the loop, you can check the count variable against the number of elements in the list and accordingly set up a ok() test.

Too messy for me.

And that’s where the Test::Deep CPAN module can really help you out

Check this sample code:

use Test::More tests => 1;
use Test::Deep;

my @items = $feed->get_items;
cmp_deeply(\@items, array_each(isa(“Item”)), “get_items”);

Great!

SOAP WSDL binding type

I recently came across a stumbling block while writing a WSDL for a Web Service. Many of the WSDL validators I tried were raising a validation error while parsing the WSDL.

Well, I learnt something new. The issue was that the WSDL had attributes defined for the XML. i.e. the XML resulting from the WSDL was making use of attributes.

The SOAP binding in the WSDL gives us a way to specify how the web service is bound to a messaging protocol, in particular the SOAP protocol for this case. This binding can be utilized in two ways: encoded or literal.

Here’s the catch. In case you use a binding of encoded, then its not possible to use attributes in your XML. Thats because each element of your XML would then have an attribute defined automatically (type), which tells you about the type of the element. For example: <x type=”xsd:int”>5</x> It would not be considered safe to put your own attributes for the x element, for the simple reason being, what if element x has an attribute named “type” defined in your WSDL? Thus most WSDL validators will either flag the WSDL as invalid or just plain refuse to include attributes in your XML.

The way to get around this in case you’re adamant on using attributes for your XML, is to use a SOAP binding of “literal”. Doing this, does not include the element type information in the XML, and you can then use attributes for your elments. Example XML: <x width=”6″>5</x>

This article provides a nice comparion about the different WSDL styles one can use.

Finance::Bank::HDFC and Template::Extract

I released Finance::Bank::HDFC version 0.14 recently. The latest release has the all important get_mini_statement() method implemented. Yes! Check your mini account statement (last 20 transactions) from the command line!

The Template::Extract module from CPAN was extremely helpful here. The account statements were available as JavaScript code in the source HTML file.


dattxn[l_count] = '10 Apr 2008';
txndesc[l_count] = "Description blah blah";
refchqnbr[l_count] = '000003009168';
datvalue[l_count] = '11 Apr 2008';
amttxn[l_count] = '0.01';
balaftertxn[l_count] = '999999.99';
coddrcr[l_count] = 'D';
l_count ++;

dattxn[l_count] = '01 Apr 2008';
txndesc[l_count] = "A millionaire?";
refchqnbr[l_count] = '037103902179';
datvalue[l_count] = '01 Apr 2008';
amttxn[l_count] = '1000000.00';
balaftertxn[l_count] = '1000000.00';
coddrcr[l_count] = 'C';
l_count ++;

Looks just like a template right? Correct. Enter Template::Extract.


Template::Extract - Use TT2 syntax to extract data from documents

This is the template code I used

# template for extracting mini statements

Readonly my $TEMPLATE_MINI_STATEMENT => <<'EOF';

[% FOREACH record %]
[% ... %]dattxn[l_count] = '[% date_transaction %]';
[% ... %]txndesc[l_count] = "[% description %]";
[% ... %]refchqnbr[l_count] = '[% ref_chq_num %]';
[% ... %]datvalue[l_count] = '[% date_value %]';
[% ... %]amttxn[l_count] = '[% amount %]';
[% ... %]balaftertxn[l_count] = '[% balance %]';
[% ... %]coddrcr[l_count] = '[% type %]';
[% END %]

EOF

After using the extract() method:

my $template = Template::Extract->new;

my $ref = $template->extract($TEMPLATE_MINI_STATEMENT, $response->content);

This is the resulting arrayref. Use it the way you want.

$ref = [
{
'amount' => '0.01',
'balance' => '999999.99',
'ref_chq_num' => '000003009168',
'date_transaction' => '10 Apr 2008',
'type' => 'D',
'date_value' => '11 Apr 2008',
'description' => 'Description blah blah'
},
{
'amount' => '1000000.00',
'balance' => '1000000.00',
'ref_chq_num' => '037103902179',
'date_transaction' => '01 Apr 2008',
'type' => 'C',
'date_value' => '01 Apr 2008',
'description' => 'A millionaire?'
}
];

For example:

foreach my $stmt_ref (@$ref) {
print "Amount: " . $stmt_ref->{amount} . "\n";
print "Balance: " . $stmt_ref->{balance} . "\n";
}