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::ID

    id 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::Name

    name 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::DateTime

    ctime 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 the fstat 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 than ctime 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::DateTime

    mtime 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 the fstat 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.

CONSTANTS & ENUMERATIONS

ABSTRACT CLASSES & MIX-INS

HELPER MODULES

TOOLS

  • ladybug-conf - Generate a .ladybugrc on the local machine

  • ladybug-edit - Edit Devel::Ladybug objects using VIM and YAML

  • ladybug-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 and subtype class prototyping functions.

  • :bool

    This imports true and false boolean constants.

  • :yield

    This imports the yield, emit, and break 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::TLDR

Devel::Ladybug::Class

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