NAME
DBIO::Candy - Sugar syntax for defining DBIO result classes
VERSION
version 0.900004
SYNOPSIS
package MyApp::Schema::Result::Artist;
use DBIO::Candy;
table 'artists';
primary_column id => {
data_type => 'integer',
is_auto_increment => 1,
};
column name => {
data_type => 'varchar',
size => 100,
};
column bio => {
data_type => 'text',
is_nullable => 1,
};
column created_at => {
data_type => 'timestamp',
set_on_create => 1,
};
column updated_at => {
data_type => 'timestamp',
set_on_create => 1,
set_on_update => 1,
};
unique_constraint [qw(name)];
has_many cds => 'MyApp::Schema::Result::CD', 'artist_id';
1;
PostgreSQL-specific example:
package MyApp::Schema::Result::User;
use DBIO::Candy -components => ['InflateColumn::DateTime', 'InflateColumn::Serializer'];
table 'users';
primary_column id => {
data_type => 'uuid',
retrieve_on_insert => 1,
};
column name => {
data_type => 'varchar',
size => 100,
};
column role => {
data_type => 'enum',
extra => { list => [qw( admin moderator user guest )] },
is_nullable => 1,
};
column metadata => {
data_type => 'jsonb',
default_value => '{}',
serializer_class => 'JSON',
};
column embedding => {
data_type => 'vector',
size => 1536,
};
column tags => {
data_type => 'text[]',
is_nullable => 1,
};
column created_at => {
data_type => 'timestamp',
set_on_create => 1,
};
column updated_at => {
data_type => 'timestamp',
set_on_create => 1,
set_on_update => 1,
};
column deleted_at => {
data_type => 'timestamp',
is_nullable => 1,
};
1;
See t/candy_indices.t for a runnable example.
DESCRIPTION
DBIO::Candy sits between vanilla DBIO::Core and DBIO::Cake. It keeps the familiar method-based API, but imports shorter helper names so result classes read more cleanly.
By default it:
turns on strict and warnings
sets your parent class to DBIO::Core
exports package methods used to define results as simple subroutines
aliases some method names for clarity
cleans the namespace after export via namespace::clean
METHODS
base
sub base { $_[1] || 'MyApp::Schema::Result' }
Class-method hook, called with the -base import value. Returns the parent class(es) to add to the result class; the default returns that value or DBIO::Core. Override in a subclass to change the default (see "SETTING DEFAULT IMPORT OPTIONS").
perl_version
Hook called with the -perl5 import value (already converted to a number from a v-string). A true return enables use feature ":5.$n" in the result class. The default returns its argument.
autotable
Hook called with the -autotable import value. A true return makes Candy set the table name from the class name on the first sugar call, using "gen_table". The default returns its argument.
experimental
Hook called with the -experimental import value. A true return must be an arrayref of feature names, which are passed to experimental. The default returns its argument.
gen_table
my $table = $candy->gen_table($class, $version);
Derives a table name from a result class name: takes the part after ::Result:: (croaking on any other naming scheme), strips :: and decamelizes. $version 'singular' returns that; 1 additionally pluralizes through Lingua::EN::Inflect. See "AUTOTABLE VERSIONS".
gen_custom_imports
my ($methods, $aliases) = $candy->gen_custom_imports($result_class);
Walks the linearised @ISA of the result class and collects the extra methods and aliases every class in it registered through DBIO::Candy::Exports. Returns an arrayref of method names and a hashref of alias to method.
parse_arguments
my $args = $candy->parse_arguments(\@import_args);
Splits the import list into the known options (-base, -autotable, -perl5, -experimental, -components, each taking the following value) and everything else. Returns { base, autotable, perl_version, components, experimental, rest => [...] }; one-character -autotable and -perl5 values (v-strings) are converted with ord.
gen_primary_column
gen_unique_column
gen_has_column
gen_indices
gen_proxy
gen_rename_proxy
Generator hooks for Sub::Exporter: each returns a generator that builds the exported sugar sub for one result class ("primary_column", "unique_column", "has_column", "indices", the plain method proxies of "IMPORTED SUBROUTINES", and the renamed ones of "IMPORTED ALIASES"). Every generated sub first applies the autotable name (once), then calls the corresponding class method on the result class.
installer
Returns the Sub::Exporter installer: the default installer, followed by namespace::clean on every installed sugar sub, so none of them remains a method of the result class.
set_base
$candy->set_base($result_class, $base);
Loads the class(es) "base" returns for $base and appends them to the result class's @ISA, skipping any already present (idempotent, so a reload does not duplicate them).
gen_INIT
Returns the INIT collector run on every import: turns on strict and warnings, enables the requested :5.N feature bundle and experimental features (dying unless the latter is an arrayref), and sets the result class's MRO to c3.
IMPORT OPTIONS
Candy is a good fit when you want lighter syntax but still prefer explicit column hashrefs over Cake's DDL-style declarations.
-base
use DBIO::Candy -base => 'MyApp::Schema::Result';
Set the parent class. Defaults to DBIO::Core.
-autotable
use DBIO::Candy -autotable => v1;
Automatically generate the table name from the class name. Version v1 pluralizes (Cat becomes cats), 'singular' does not.
-components
use DBIO::Candy -components => ['InflateColumn::DateTime'];
Load components at import time so they can register their own sugar via DBIO::Candy::Exports.
-perl5
use DBIO::Candy -perl5 => v10;
Enable Perl feature flags (equivalent to use feature ':5.10').
-experimental
use DBIO::Candy -experimental => ['signatures'];
Enable experimental features.
IMPORTED SUBROUTINES
The following are exported with the same name and arguments as their __PACKAGE__->method equivalents:
belongs_to
has_many
has_one
inflate_column
many_to_many
might_have
remove_column
remove_columns
resultset_attributes
resultset_class
sequence
source_name
table
IMPORTED ALIASES
Shorter or clearer names for common methods:
column => 'add_columns'
primary_key => 'set_primary_key'
unique_constraint => 'add_unique_constraint'
relationship => 'add_relationship'
TRANSFORMER FUNCTIONS
has_column
has_column foo => (
data_type => 'varchar',
size => 25,
);
Like add_columns but takes a flat list of key/value pairs (Moose-style) and wraps them into a hashref.
primary_column
primary_column id => {
data_type => 'int',
is_auto_increment => 1,
};
Defines a column and adds it to the primary key in a single call.
unique_column
unique_column name => {
data_type => 'varchar',
size => 30,
};
Defines a column and adds a unique constraint on it in a single call.
indices
indices(
name_idx => 'name',
name_email_idx => ['name', 'email'],
);
Declares one or more secondary indexes on the table. Field lists may be a single column name or an arrayref of column names. Equivalent to the DBICx::Indexing component on DBIx::Class. Each index is stored as a canonical declaration on the result source ("index_declarations" in DBIO::ResultSource), which the native driver deploy path reads.
SETTING DEFAULT IMPORT OPTIONS
Create a subclass to avoid repeating import options:
package MyApp::Schema::Candy;
use base 'DBIO::Candy';
sub base { $_[1] || 'MyApp::Schema::Result' }
sub perl_version { 12 }
sub autotable { 1 }
sub experimental { ['signatures'] }
Then in your result classes:
use MyApp::Schema::Candy;
AUTOTABLE VERSIONS
v1
Extracts the part after ::Result::, removes ::, decamelizes, and pluralizes:
MyApp::Schema::Result::Cat -> cats
MyApp::Schema::Result::LonelyPerson -> lonely_people
'singular'
Same as v1 but without pluralization:
MyApp::Schema::Result::Cat -> cat
MyApp::Schema::Result::LonelyPerson -> lonely_person
TIMESTAMP HELPERS
These are proxy methods for DBIO::Timestamp (loaded automatically):
col_created
col_created; # creates 'created_at' column
col_created 'born_at'; # custom column name
col_updated
col_updated; # creates 'updated_at' column
col_updated 'modified_at'; # custom column name
cols_updated_created
cols_updated_created; # creates both at once
The most common pattern -- one line for both timestamp columns.
AUTHOR
DBIO & DBIx::Class Authors
COPYRIGHT AND LICENSE
Copyright (C) 2026 DBIO Authors Portions Copyright (C) 2005-2025 DBIx::Class Authors Based on DBIx::Class, heavily modified.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.