This is something I did at work just before Christmas, which is kind of useful.
Some years ago, I came up with the original method do_transaction()
for Class::DBI. However, it’s kind of clunky to use, as the example shows.
Music::DBI->do_transaction( sub { my $artist = Music::Artist->insert({ name => 'Pink Floyd' }); my $cd = $artist->add_to_cds({ title => 'Dark Side Of The Moon', year => 1974, }); });
The thing that bugs me in particular is the mandatory use of sub {}
. I’d rather it be like ruby’s blocks, more of a language feature. Thankfully, Perl allows you to do this with prototypes.
So I modified my base class for Class::DBI to look like this:
use Exporter 'import'; our @EXPORT = qw( do_transaction ); sub do_transaction (&) { my $class = __PACKAGE__; # Rest of function remains the same. }
This lets you call do_transaction in a much simpler fashion:
use Music::DBI; do_transaction { my $artist = Music::Artist->insert({ name => 'Pink Floyd' }); my $cd = $artist->add_to_cds({ title => 'Dark Side Of The Moon', year => 1974, }); }
Now I have committed one of the cardinal sins of Perl OO here—I’m exporting from an OO module. In this case though, I feel it’s justified. Firstly, you need to call the function as a function and not a method for the prototype to have any effect. Secondly, it greatly reduces the amount of typing that I have to do. Overall, it’s a much nicer solution.
Of course, Ruby on Rails makes this much simpler, because it’s notion of blocks is so deeply embedded into the language. See ActiveRecord::Transactions::ClassMethods for details.