NAME

Fey::ORM::Table - Provides sugar for table-based classes

VERSION

version 0.47

SYNOPSIS

package MyApp::User;

use Fey::ORM::Table;

has_table ...;

no Fey::ORM::Table;

DESCRIPTION

Use this class to associate your class with a table. It exports a number of sugar functions to allow you to define things in a declarative manner.

EXPORTED FUNCTIONS

This package exports the following functions:

has_table($table)

Given a Fey::Table object, this method associates that table with the calling class.

Calling has_table() will make your class a subclass of Fey::Object::Table, which provides basic CRUD operations for Fey::ORM. You should make sure to review the docs for Fey::Object::Table.

Calling this function also generates a number of methods and attributes in the calling class.

First, it generates one attribute for each column in the associated table. Of course, this assumes that your columns are named in such a way as to be usable as Perl methods.

It also generates a predicate for each attribute, where the predicate is the column named prefixed with "has_". So for a column named "user_id", you get a user_id() attribute and a has_user_id() predicate.

These column-named attributes do not have a public setter method. If you want to change the value of these attributes, you need to use the update() method.

has_policy($policy_class)

has_policy($policy_object)

This allows you to associate a policy with your class. See Fey::ORM::Policy for details on how policies work.

has_one($table)

has_one 'name' => ( table => $table, fk => $fk, cache => $bool, undef => $bool, handles => ... )

The has_one() function declares a relationship between the calling class's table and another table. The method it creates returns an object of the foreign table's class, or undef or none exists.

With the single-argument form, you can simply pass a single Fey::Table object. This works when there is a single foreign key between the calling class's table and the table passed to has_one().

With a single argument, the generated attribute will be named as lc $has_one_table->name(), and caching will be turned on.

If you want to change any of the defaults, you can use the multi-argument form. In this case, the first argument is the name of the attribute or method to add. Then you can specify various parameters by name. You must specify a table, of course.

The fk parameter is required when there is more than one foreign key between the two tables. Finally, you can turn off caching by setting cache to a false value.

When caching is enabled, the object for the foreign table is only fetched once, and is cached afterwards. This is independent of the object caching for a particular class. If you turn off caching, then the object is fetched every time the method is called.

Also, a private clearer method is created when caching is enabled, of the form $object->_clear_$name().

The undef parameter allows you to explicitly say whether the attribute can be undefined. Normally this is calculated by looking at the foreign key and seeing if any of the source columns are nullable.

The handles parameter works exactly like it does for any Moose attribute, but it only works if cache is true, since otherwise the relationship is implemented via a simple method, not a Moose attribute.

has_one 'name' => ( table => $table, select => $select, bind_params => $sub, cache => $bool, undef => $bool, handles => ... )

This is an alternative form of has_one() that lets you declare a relationship to another table via an arbitrary SELECT statement.

In this form, you provide a query object to define the SQL used to fetch the foreign row. You can provide a bind_params parameter as a code reference, which will be called as a method on your object. It is expected to return one or more bind parameters. The cache parameter works exactly the same as in the first form of has_one().

In this form the undef parameter defaults to true, but you can set it to a false value.

Note that if you want to provide bind_params for the SQL you provide, you need to make sure it has placeholders.

has_many($table)

has_many 'name' => ( table => $table, fk => $fk, cache => $bool, order_by => [ ... ] )

The has_many() function declares a relationship between the calling class's table and another table, just like has_one(). The method it creates returns a Fey::Object::Iterator::FromSelect of the foreign table's objects.

With the single-argument form, you can simply pass a single Fey::Table object. This works when there is a single foreign key between the calling class's table and the table passed to has_many().

With a single argument, the generated attribute will be named as lc $has_one_table->name(), and caching will be turned off. There will be no specific order to the results returned.

If you want to change any of the defaults, you can use the multi-argument form. In this case, the first argument is the name of the attribute or method to add. Then you can specify various parameters by name. You must specify a table, of course.

The fk parameter is required when there is more than one foreign key between the two tables. Finally, you can turn on caching by setting cache to a true value.

When caching is enabled, the iterator returned is of the Fey::Object::Iterator::FromSelect::Caching class.

Also, a private clearer method is created when caching is enabled, of the form $object->_clear_$name().

Note that you will always get an iterator object back from your has_many methods and attributes, even if there are no matching rows in the foreign table.

You can also specify an order_by parameter as an array reference. This should be an array like you would pass to Fey::SQL::Select->order_by().

query $name => select => $select, bind_params => sub { ... }

The query() function declares a method based on the given query. This works much like declaring an attribute with the FromSelect metaclass, but the value returned from the query is not stored in the object.

transform $column1, $column2 => inflate { ... } => deflate { ... }

The transform() function declares an inflator, deflator, or both for the specified column. The inflator will be used to wrap the normal accessor for the column. You'd generally use this to turn a raw value from the DBMS into an object, for example:

transform 'creation_date' =>
    inflate { DateTime::Format::Pg->parse_date( $_[1] ) };

The inflator (and deflator) coderef you specify will be called as a method on the object (or class). This lets you get at other attributes for the object if needed.

When a column is inflated, a new attribute is created to allow you to get at the raw data by suffixing the column name with "_raw". Given the above inflator, a creation_date_raw() attribute would be created.

If the column in question is nullable your inflator should be prepared to handle an undef value for the column.

Deflators are used to transform objects passed to update() or insert() into values suitable for passing to the DBMS:

transform 'creation_date' =>
    deflate { defined $_[1] && ref $_[1]
                ? DateTime::Format::Pg->format_date( $_[1] )
                : $_[1] };

Just as with an inflator, your deflator should be prepared to accept an undef if the column is nullable.

You can only declare one inflator and one deflator for each column.

You can use the same inflator and deflator for more than one column at once:

transform 'creation_date', 'modification_date'
    => inflate { ... }
    => deflate { ... };

inflate { .. }

deflate { .. }

These are sugar functions that accept a single coderef. They mostly exist to prevent you from having to write this:

# this is not valid code!
transform 'creation_date' =>
    ( inflator => sub { ... },
      deflator => sub { ... },
    );

handles ...

This sugar function lets you add delegation to an inflated attribute. It accepts anything that Moose accepts for an attribute's handles parameter.

transform 'creation_date'
    => inflate { ... }
    => handles { creation_ymd     => 'ymd',
                 creation_iso8601 => 'iso8601',
               }
    => deflate { ... };

AUTHOR

Dave Rolsky <autarch@urth.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2011 - 2015 by Dave Rolsky.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.