package Table; use DBI; use Moose; use Moose::Exporter; Moose::Exporter->setup_import_methods( with_caller => [ 'has_table' ] ); sub has_table { my $class = shift; my $table = shift; my %args = @_; my $rows = _get_table_rows( $table ); # this is just so client doesn't have to pass table name to load() $class->meta->add_attribute( '_table', is => 'ro', reader => 'table', default => $table ); for my $row (@$rows) { $class->meta->add_attribute( $row->{Field}, is => 'rw' ); } } sub load { my $self = shift; my %args = @_; my %fields = map { /^set_(\w+)$/; $1 => $_ } grep /^set_/, map $_->name, $self->meta->get_all_methods ; my $dbh = DBI->connect( ... ); my $table = $self->table; my $fields = join( ', ', keys %fields ); my $record = $dbh->selectrow_hashref( "select $fields from $table where id = ?", undef, $self->get_id ); for my $field (keys %fields) { my $writer = $fields{$field}; $self->$writer( $record->{$field} ); } } package Table::Loader; use Moose::Role; sub BUILD { my $self = shift; if ($self->get_id) { Table::load( $self, id => $self->get_id ); } } package MyTable; use Moose::Policy 'Moose::Policy::FollowPBP'; use Moose; use Table; with 'Table::Loader'; has_table 'my_table'; # psuedo code package main; my $table = MyTable->new( id => 1 );