Archive

Archive for the ‘Perl’ Category

Module::Info – why didn’t I look for this eariler?

March 15, 2011 4 comments

Just a quick post in praise of Module::Info. I often find myself wanting to know the version or location of a CPAN module installed on a particular system. Too often, I end up doing:

perl -MSome::Module -le "print $Some::Module::VERSION"

and/or:

perl -MSome::Module -le "print $INC{'Some/Module.pm'}"

Quite cumbersome and verbose. I’ve often thought someone could easily write a script to provide this, and even wondered if I should do this myself. The urge to scratch that itch has never become overpowering enough, however.

Today, though, I decided I should actually see if someone had already done it. It took all of 2 seconds to turn up Module::Info, which comes with a command line tool. I can now write the above commands as:

module_info Some::Module

It even tells me if it’s a core module, and can display its dependencies with the right command line parameters. Even better, there are packages for Debian and Ubuntu. What more could I ask for?

So Module::Info++, and now I have to start wondering why I didn’t take the time to look for this tool some time ago…

Advertisements
Categories: Perl Tags:

DBIx::Class and dynamic roles

May 25, 2010 2 comments

The DBIx::Class Cookbook already documents how to dynamically create objects in a particular subclass rather than the table’s base class. This is a very useful approach if you have objects that need to work differently based on certain a certain column in a table. (DBIx::Class::DynamicSubclass also does a lot of the work for you).

But what if you want to make use of Moose roles instead of sub-classes (as we often do when using Modern Perl)? It’s easy! In the schema class for the table, just add:

sub inflate_result {
    my $pkg = shift;

    my $self = $pkg->next::method(@_);

    $self->_apply_role;

    return $self;
}

sub _apply_role {
    my $self = shift;
	
    my $role = $self->get_role_name;
    $self->ensure_class_loaded($role);	
    $role->meta->apply($self);	
}

This overrides inflate_result() in the same way as the example in the DBIx::Class cookbook, except that we apply a role, instead of blessing into a different class. Note, you’ll need to define the get_role_name() method. This returns the name of the role’s package (as a string), which you should derive from the object’s data somehow. For instance, you might check if the object has the column ‘admin’ set to true, and if so apply the ‘Admin’ role.

It can also be useful to insert some rows in other columns when the object is first created. To do this, override the insert method:

sub insert {
    my ( $self, @args ) = @_;
	
    $self->next::method(@args);
	
    $self->_apply_role;
	
    $self->init;
}

The ‘init’ method (you might want to use a better name) is on the role that’s applied, so could be different depending on the special things that that role needs to do. For instance, maybe anything with the ‘Admin’ role needs some extra rows inserted into a related table to keep track of which admin permissions a user has. How this init() method operates can either be derived from the data, or passed in via a custom ResultSet method that creates the object.

Note that as you’re calling methods from the roles in your schema class (and potentially vice verca) you probably want to make careful use of the ‘requires’ keyword in your roles, to ensure all the necessary methods are defined somewhere.

Of course, this example only applies one role, but there’s no reason get_role_name() couldn’t be adapted to return multiple role packages, each of which are applied to the object.

Categories: Perl