NAME
Devel::Ladybug - Data modeling framework
SYNOPSIS
use strict;
use warnings;
use Devel::Ladybug qw| :all |;
create "YourApp::YourClass" => { };
See PROTOTYPE COMPONENTS in Devel::Ladybug::Class for detailed examples.
DESCRIPTION
Devel::Ladybug is a framework for creating and working with data models.
Using the create()
function, developers may assert rules for classes. Devel::Ladybug creates a permanent backing store for these classes, and can also handle object-relational mapping and input validation.
Supported storage types are YAML or JSON flatfile, MySQL (InnoDB engine), PostgreSQL, and SQLite. Memcached, DBIx::TextIndex, and RCS may be used in conjunction with the permanent backing store.
VERSION
This documentation is for version 0.412_01 of Devel::Ladybug.
FRAMEWORK ASSUMPTIONS
As with any framework, a number of things "just happen" by design. Trying to go against the flow of these base assumptions is not recommended.
Configuration
See CONFIGURATION AND ENVIRONMENT in this document.
Table Creation
Database schemas are derived from the assertions contained in object classes. Devel::Ladybug creates any needed tables.
Default Base Attributes
Persistent objects always have "id", "name", "ctime", and "mtime".
id
=> Devel::Ladybug::IDid
is the primary key at the database table level. The gets used in database table indexes, and should generally not be altered once assigned.Base64-encoded Globally Unique IDs are used by default, though it is possible to assert any scalar Devel::Ladybug object class for the
id
column. See Devel::Ladybug::ID, Devel::Ladybug::Serial.name
=> Devel::Ladybug::Namename
is a secondary human-readable key.The assertions for the name attribute may be changed to suit a class's requirements, and the name value for any object may be freely changed.
For more information on named objects, see Devel::Ladybug::Name.
ctime
=> Devel::Ladybug::DateTimectime
is an object's creation timestamp. Devel::Ladybug sets this when saving an object for the first time.This is not the same as, and should not be confused with, the
st_ctime
filesystem attribute returned by thefstat
system call, which represents inode change time for files. If this ends up being too confusing or offensive, Devel::Ladybug may use a name other thanctime
for creation time in a future version. It is currently being left alone.For more information on timestamps, see Devel::Ladybug::DateTime.
mtime
=> Devel::Ladybug::DateTimemtime
is the Unix timestamp representing an object's last modified time. Devel::Ladybug updates this each time an object is saved.Again, this is an object attribute, and is unrelated to the
st_mtime
filesystem attribute returned by thefstat
system call. Devel::Ladybug may use a different name in a future version.
undef
Requires Assertion
Saved instance variables may not be undef (and the corresponding table column may not contain NULL) unless the instance variable was explicitly asserted as optional in the class prototype. To do so, provide "optional" as an assertion argument, as in the following example:
create "YourApp::Example" => {
### Do not permit NULL:
someMandatoryDate => Devel::Ladybug::DateTime->assert,
### Permit NULL:
someOptionalDate => Devel::Ladybug::DateTime->assert(
subtype(
optional => true,
)
),
# ...
};
Namespace Matters
Devel::Ladybug's core packages live under the Devel::Ladybug:: namespace. Your classes should live in their own top-level namespace, e.g. "YourApp::YourClass".
The top level namespace (eg "YourApp") translates, in lower case, to the name of the app's database. The database name may be overridden by implementing class method databaseName
.
Namespace elements beyond the top-level translate to lower case table names. In cases of nested namespaces, Perl's "::" delineator is swapped out for an underscore (_). The table name may be overridden by implementing class method tableName
.
create "YourApp::Example::Foo" => {
# overrides default value of "yourapp"
databaseName => sub {
my $class = shift;
return "some_legacy_db";
},
# overrides default value of "example_foo"
tableName => sub {
my $class = shift;
return "some_legacy_table";
},
# ...
};
OBJECT TYPES
Devel::Ladybug object types are used when asserting attributes within a class, and are also suitable for instantiation or subclassing in a self-standing manner.
The usage of these types is not mandatory outside the context of creating a new class-- Devel::Ladybug always returns attributes from the database in object form, but these object types are not a replacement for Perl's native data types in general usage, unless the developer wishes them to be.
These modes of usage are shown below, and covered in greater detail in specific object class docs.
DECLARING AS SUBCLASS
By default, a superclass of Devel::Ladybug::Node is used for new classes. This may be overridden using __BASE__:
use Devel::Ladybug qw| :all |;
create "YourApp::Example" => {
__BASE__ => "Devel::Ladybug::Hash",
# ...
};
ASSERTING AS ATTRIBUTES
When defining the allowed instance variables for a class, the assert()
method is used:
#
# File: Example.pm
#
use Devel::Ladybug qw| :all |;
create "YourApp::Example" => {
someString => Devel::Ladybug::Str->assert,
someInt => Devel::Ladybug::Int->assert,
};
INSTANTIATING AS OBJECTS
When instantiating, the class method new()
is used, typically with a prototype object for its argument.
#
# File: somecaller.pl
#
use strict;
use warnings;
use YourApp::Example;
my $example = YourApp::Example->new(
name => "Hello",
someString => "foo",
someInt => 12345,
);
$example->save;
$example->print;
IN METHODS
Constructors and setter methods accept both native Perl 5 data types and their Devel::Ladybug object class equivalents. The setters automatically handle any necessary conversion, or throw an exception if the received arg doesn't quack like a duck.
To wit, native types are OK for constructors:
my $example = YourApp::Example->new(
someString => "foo",
someInt => 123,
);
#
# someStr became a string object:
#
say $example->someString->class;
# "Devel::Ladybug::Str"
say $example->someString->length;
# "3"
say $example->someString;
# "foo"
#
# someInt became an integer object:
#
say $example->someInt->class;
# "Devel::Ladybug::Int"
say $example->someInt->sqrt;
# 11.0905365064094
say $example->someInt;
# 123
Native types are OK for setters:
$example->setSomeInt(456);
say $example->someInt->class;
# "Devel::Ladybug::Int"
CORE OBJECT TYPES
The basic types listed here may be instantiated as objects, and asserted as inline attributes.
Devel::Ladybug::Array - List
Devel::Ladybug::Bool - Overloaded boolean
Devel::Ladybug::DateTime - Overloaded time object
Devel::Ladybug::Double - Overloaded double-precision number
Devel::Ladybug::ExtID - Overloaded foreign key
Devel::Ladybug::Float - Overloaded floating point number
Devel::Ladybug::Hash - Hashtable
Devel::Ladybug::ID - Overloaded GUID primary key
Devel::Ladybug::Int - Overloaded integer
Devel::Ladybug::Name - Unique secondary key
Devel::Ladybug::Num - Overloaded number
Devel::Ladybug::Rule - Regex reference (qr/ /)
Devel::Ladybug::Serial - Auto-incrementing primary key
Devel::Ladybug::Str - Overloaded unicode string
Devel::Ladybug::TimeSpan - Overloaded time range object
CONSTANTS & ENUMERATIONS
Devel::Ladybug::Constants - "dot rc" values as constants
Devel::Ladybug::Enum - C-style enumerated types as constants
ABSTRACT CLASSES & MIX-INS
Devel::Ladybug::Class - Abstract "Class" class
Devel::Ladybug::Class::Dumper - Introspection mix-in
Devel::Ladybug::Node - Abstract stored object class
Devel::Ladybug::Object - Abstract object class
Devel::Ladybug::Persistence - Storage and retrieval mix-in
Devel::Ladybug::Persistence::Generic - Abstract base for DBI mixins
Devel::Ladybug::Persistence::MySQL - MySQL/InnoDB overrides
Devel::Ladybug::Persistence::PostgreSQL - PostgreSQL overrides
Devel::Ladybug::Persistence::SQLite - SQLite overrides
Devel::Ladybug::Stream - Buffered iterator for table rows
Devel::Ladybug::Scalar - Base class for scalar values
Devel::Ladybug::Subtype - Instance variable subtyping
Devel::Ladybug::Type - Instance variable typing
HELPER MODULES
Devel::Ladybug::Utility - System functions required globally
Devel::Ladybug::Exceptions - Errors thrown by Devel::Ladybug
TOOLS
ladybug-conf
- Generate a .ladybugrc on the local machineladybug-edit
- Edit Devel::Ladybug objects using VIM and YAMLladybug-dump
- Dump Devel::Ladybug objects to STDOUT in various formats
EXPORT TAGS
All exports are optional. Specify a tag or symbol by name to import it into your caller's namespace.
use Devel::Ladybug qw| :all |;
:all
This imports each of the symbols listed below.
:create
This imports the
create
andsubtype
class prototyping functions.:bool
This imports
true
andfalse
boolean constants.:yield
This imports the
yield
,emit
, andbreak
functions for array collectors; see Devel::Ladybug::Array.
CONFIGURATION AND ENVIRONMENT
Devel::Ladybug and your DBA
If using MySQL or PostgreSQL, your app's database and the "ladybug" database should exist with the proper access prior to use - see Devel::Ladybug::Persistence::MySQL, Devel::Ladybug::Persistence::PostgreSQL.
LADYBUG_HOME and .ladybugrc
Devel::Ladybug looks for its config file, .ladybugrc
, under $ENV{LADYBUG_HOME}. LADYBUG_HOME defaults to the current user's home directory.
To generate a first-time config for the local machine, copy the .ladybugrc (included with this distribution as ladybugrc-dist
) to the proper location, or run ladybug-conf
(also included with this distribution) as the user running Devel::Ladybug.
See Devel::Ladybug::Constants for information regarding customizing and extending the local rc file.
Devel::Ladybug and mod_perl
Devel::Ladybug-based classes used in a mod_perl app should be preloaded by a startup script. LADYBUG_HOME must be set in the script's BEGIN block.
For example, in a file startup.pl
:
use strict;
use warnings;
BEGIN {
#
# Directory with the .ladybugrc:
#
$ENV{LADYBUG_HOME} = '/your/ladybug/home';
}
use YourApp::Component;
use YourApp::OtherComponent;
1;
The startup script should be specified in httpd.conf. Additionally, you may need to include a PerlSetEnv directive, for example:
PerlRequire /path/to/your/startup.pl
<LocationMatch "/.*\.html$">
SetHandler perl-script
PerlHandler HTML::Mason::ApacheHandler
PerlSetEnv LADYBUG_HOME /your/ladybug/home
</LocationMatch>
INSTALLATION
Ease of installation is one of Devel::Ladybug's goals. The only build requirements are a compiler (gcc
or equivalent is needed by CPAN to build a few dependencies), and a working Perl 5 (5.8.8 or greater). Devel::Ladybug's prerequisite Perl packages are handled by CPAN, and generally install with no fuss. These are listed in Makefile.PL.
FROM CPAN (RECOMMENDED)
The recommended way to install Devel::Ladybug is via CPAN:
perl -MCPAN -e 'install Devel::Ladybug'
Answer "yes" when prompted to install dependencies. You must (of course) have permission on your local system to do so, which means you either have superuser access, or your user owns the Perl install.
Devel::Ladybug does not depend on any particular DBI driver-- the package of your choice needs to be installed separately in order to be usable by Devel::Ladybug as a backing store type. Currently supported drivers are: DBD::mysql, DBD::Pg, and DBD::SQLite.
FROM SOURCE
Assuming dependencies have been installed, installation may also be done manually:
cd Devel-Ladybug-xxxx
perl Makefile.PL # Warns if system is missing prereqs
make test
make install
INSTALL PROBLEMS?
The most common installation problem is due to a compiler not being present on the local machine. After installing gcc, you may need to purge the contents of the CPAN build directory to avoid cached failed build results (e.g. ~root/.cpan/build/*), and re-run the installation.
Refer to recent CPAN Testers results to see if Devel::Ladybug "should" work with your particular software stack. Installation problems may be reported to the author via email (please include the output from make test
)
http://static.cpantesters.org/distro/D/Devel-Ladybug.html
BUGS AND LIMITATIONS
This code is now in maintenance mode, and is unlikely to receive significant new features. There are several similar frameworks on CPAN which are more active, you may want to check those out first.
Tests show that Ladybug objects have precision problems, if Perl was built with long double support. This is a compilation issue with one of Ladybug's dependencies, and has not been isolated.
SEE ALSO
Devel::Ladybug is on GitHub: http://github.com/aayars/ladybug
SUPPORT
Support is available from the author via email.
AUTHOR
Alex Ayars <pause@nodekit.org>
LICENSE AND COPYRIGHT
Copyright (c) 2009 TiVo Inc.
Copyright (c) 2010 Alex Ayars
All rights reserved. This program and the accompanying materials
are made available under the terms of the Common Public License v1.0
which accompanies this distribution, and is available at
http://opensource.org/licenses/cpl1.0.txt