For quite a while, my co-conspirators and I have been bouncing around better syntax for DBIx::SearchBuilder, the object-relational mapper RT's built on. We eventually decided to take the plunge and fork it into Jifty::DBI -- a new tool to do the same thing, just better.
One of the things that we've spent a fair bit of time on is the syntax for declaring your schema in perl. From this syntax, we can generate a table in the database, viewy bits in our web toolkit (you'll be hearing more about that later), accessors, validators and even automatically upgrade the database schema if you're starting from an older version. A quick copy-and-paste example from some code we're working on is below.
And no, this doesn't use any source filters.
package BTDT::Model::Task::Schema;
use Jifty::DBI::Schema;
use BTDT::Model::TaskTagCollection;
column complete =>
type is 'boolean',
default is 'false',
since '0.1.1',
label is 'Done';
column summary =>
type is 'varchar',
label is 'Task',
hints is '(Example: Pick up milk at the store)';
column description =>
type is 'text',
render_as 'Textarea',
label is 'Details';
column owner_id =>
refers_to BTDT::Model::User,
label is 'Owner',
render_as 'Combobox';
column starts =>
type is 'date',
render_as 'Date',
label 'Defer until';
column due =>
type is 'date',
render_as 'Date',
label is 'Date due';
column priority =>
type is 'integer',
since '0.2.11',
default is 3,
label is 'Priority',
valid_values are
{ display => 'highest', value => 5 },
{ display => 'high', value => 4 },
{ display => 'normal', value => 3 },
{ display => 'low', value => 2 },
{ display => 'lowest', value => 1 };
column tags =>
since '0.1.7',
label is 'Tags',
refers_to BTDT::Model::TaskTagCollection by 'task_id';
package BTDT::Model::Task;
use BTDT::Model::User;
use BTDT::Model::Group;
use base qw( BTDT::Record );
# Methods on your Task object go here
=head2 text_priority
Returns the priority as a string, not as a number.
=cut
sub text_priority {
my $self = shift;
my $number = shift || $self->priority;
my %mapping;
$mapping{$_->{value}} = $_->{display} for @{$self->column("priority")->valid_values};
return $mapping{$number};
}