I wrote about using the Perl debugger with Moose. In that post, I showed how to use DB::Skip to make it easier to use the Perl debugger with Moose and other modules whose guts you don't want to wade through.

Today's debugger hack will make using the debugger with DBIx::Class much easier.

If you're a fan of the debugger, one thing which makes life miserable is being in the debugger and accidentally doing something like this:

121: local config(qw'logging LogEvent')->{Exchange} = 1; 122: $DB::single = 1; 123==> my $wallet = $character->wallet; 124 125: my $exchange = $class->new( 126 principal => $character, 127 slug => 'test_check_success', 128 steps => [ [ TestWallet => check => $character => $wallet ] ] 129 ); DB<2> x $character

With that, you get hundreds of lines of output scrolling past, too fast to read. And forget about going back in your buffer trying to find the data you need. It's a nightmare.

So I hijacked the p command in the debugger. In perldoc perldebug, we see that p is for this:

p expr Same as print {$DB::OUT} expr in the current package. In particular, because this is just Perl's own print function, this means that nested data structures and objects are not dumped, unlike with the x command. The DB::OUT filehandle is opened to /dev/tty , regardless of where STDOUT may be redirected to.

To be honest, I don't find that very useful. So I altered it to make a quick "dump" of a data structure, with one interesting caveat. Unless it's an array or hash reference, it's stringified. So the above debugging session becomes this (I've truncated some data to hide some important gameplay):

121: local config(qw'logging LogEvent')->{Exchange} = 1; 122: $DB::single = 1; 123==> my $wallet = $character->wallet; 124 125: my $exchange = $class->new( 126 principal => $character, 127 slug => 'test_check_success', 128 steps => [ [ TestWallet => check => $character => $wallet ] ] 129 ); DB<2> p $character Veure::Model::DB::Character=HASH(0x7fcd6feb5de8) DB<3> p {%$character} { '_column_data' => { 'agility' => '10', 'arrival' => '2017-03-27 09:44:33.546391000+0000', 'career_path_id' => '', 'character_id' => '15538', 'conscious' => '1964-01-22 00:00:00+0000', 'curr_agility' => '1', 'curr_intelligence' => '1', 'curr_social' => '1', 'curr_stamina' => '1', 'curr_strength' => '1', 'current_ship_id' => '', 'experience' => '800', 'focus' => '1', 'genotype_id' => '1', 'intelligence' => '10', 'inventory_id' => '17762', 'last_activity' => '2017-03-27 09:44:33+0000', 'last_station_area_id' => '1199', 'modifier_list_id' => '', 'name' => 'winston', 'slug' => 'winston', 'social' => '10', 'stamina' => '10', 'station_area_id' => '1199', 'strength' => '10', 'user_id' => '14554', 'wallet' => '10' }, '_dirty_columns' => {}, '_ignore_messages' => '0', '_in_storage' => '1', '_inflated_column' => { 'arrival' => '2017-03-27T09:44:33', 'conscious' => '1964-01-22T00:00:00', 'last_activity' => '2017-03-27T09:44:33' }, '_rel_in_storage' => {}, '_relationship_data' => { 'bank_account' => 'Veure::Model::DB::BankAccount=HASH(0x7fcd6fec3460)', 'character_user' => 'Veure::Model::DB::User=HASH(0x7fcd6fed6f08)', 'inventory' => 'Veure::Model::DB::Inventory=HASH(0x7fcd71137110)' }, '_result_source' => 'DBIx::Class::ResultSource::Table=HASH(0x7fcd6b7ce350)', 'app' => 'Veure::App=HASH(0x7fcd6b79aa08)', 'related_resultsets' => {} }

Now dumping that data structure is actually useful and it's trivial for me to find the information I need!

You can get the source of my debugger hack here. Save that as .perldb in your home directory.

Hire Us!

As always, if you want top-notch software development or training, or help building your test suite, drop me a line at ovid at allaroundtheworld.fr. Most of us are Perl devs, but we also do front-end development, Golang, C++, Lua, and Python. Due to our extensive links in multiple software communities, if you need an expert in another language, let me know.