Oryx - Meta-Model Driven Object Persistance with Multiple Inheritance
#=========================================================================== # connect to storage $storage = Oryx->connect(['dbi:Pg:dbname=cms', $usname, $passwd]); # or specify a schema $storage = Oryx->connect( ["dbi:Pg:dbname=cms", $usname, $passwd], 'CMS::Schema' ); # for DBM::Deep back-end Oryx->connect(['dbm:Deep:datapath=/path/to/data'], 'CMS::Schema'); #=========================================================================== # deploy the schema $storage->deploySchema(); # for all known classes (via `use') $storage->deploySchema('CMS::Schema'); $storage->deployClass('CMS::Page'); # automatically deploy as needed use Oryx ( auto_deploy => 1 ); # for all classes CMS::Page->auto_deploy(1); # only for this class
Oryx is an object persistence framework which supports both object-relational mapping as well as DMB style databases and as such is not coupled with any particular storage back-end. In other words, you should be able to swap out an RDMBS with a DBM style database (and vice versa) without changing your persistent classes at all.
This is achieved with the use a meta model which fits in as closely with Perl's own as possible - and due to Perl's excellent introspection capabilities and enormous flexibility - this is very close indeed. For this reason Hash, Array and Reference association types are implemented with liberal use of `tie'. The use of a meta model, albeit a very transparent one, conceptually supports the de-coupling of storage back-end from persistent classes, and, for the most part, beside a really small amout of meta-data, you would use persistent classes in a way that is virtually indistinguishable from ordinary perl classes.
Oryx follows the DRY principle - Don't Repeat Yourself - inspired by the fantastic Ruby on Rails framework, so what you do say, you say it only once when defining your $schema for your class. After that, everything is taken care of for you, including automatic table creation (if you're using an RDBMS storage). Oryx attempts to name tables and link tables created in this way sensibly, so that if you need to you should be able to find your way around in the schema with ease.
$schema
Because Oryx implements relationships as ordinary Perl Array and Hash references, you can create any structures or object relationships that you could create in native Perl and have these persist in a database. This gives you the flexibility to create trees, cyclic structures, linked lists, mixed lists (lists with instances of different classes), etc.
Oryx also supports multiple inheritance by Perl's native use base mechanism. Abstract classes, which are simply classes with no attributes, are meaningful too, see Oryx::Class for details.
use base
Oryx::Class also now inherits from Class::Observable, see relevant docs.
This documentation applies to classes persisted in DBM::Deep style storage as well except insofar as the implementation details are concerned where tables and columns are mentioned - separate files are used for DBM::Deep based storage instead of tables (see Oryx::DBM for details).
This is still an early release and supports DBM::Deep, MySQL, SQLite and Postgres back-ends at the moment. Having said this, Oryx is already quite usable. It needs to be thrashed a lot more and support for the rest of the popular RDBMS needs to be added. Things will change (for the better, one hopes); if you're interested in helping to precipitate that change... let me know, you'd be most welcome.
The documentation is in the process of being divided up between the different components:
Contains the details for defining persistent classes and how to use them. Read this first.
Describes Associations meta-types in more detail.
Explains Attribute meta-types.
All about Inheritance in Oryx.
A description of our DB friendly primitive types.
Oryx meta-model and internals for developers.
The call to Oryx->connect(...) specifies the dsn and connection credentials to use when connecting where applicable. For DBM::Deep style storage, the connection arguments look like this:
Oryx->connect(['dbm:Deep:datapath=/path/to/data'], 'CMS::Schema');
For RDBMS (Postgres in this case) it may look like this:
Oryx->connect(["dbi:Pg:dbname=cms", $usname, $passwd], 'CMS::Schema');
The Schema defaults to 'Oryx::Schema' and is therefore optional, so we could say Oryx->connect([ ... dsn ... ]), and forget about passing in a Schema.
One advantage to using separate Schema classes is that this gives you namespace separation where you need to connect several sets of classes to different storage back ends (especially where these are mixed in such a way where the same classes exist in different stores). Another advantage is that the Schema class may define a prefix method which simply returns a string to prefix table names with, for those of us who only get a single database with our hosting package and need to have some namespace separation.
Here's an example of a Schema class :
package CMS::Schema; use base qw(Oryx::Schema); # optionaly include your classes use CMS::Page; use CMS::Paragraph; use CMS::Image; sub prefix { 'cms' } 1;
If you've built a large schema and would like to deploy it in one shot, or have written an install script, then you can use all the classes near the top of your script somewhere, or in your schema class, and call deploySchema(). Note, however, that this will only have to be done once as you will generally get errors if you try to create a table more than once in your RDBMS.
use
deploySchema()
Ordinarily, though you would turn on auto_deploy for your classes, either by saying:
auto_deploy
use Oryx(auto_deploy => 1);
or if you prefer, then you can set it on a per class basis:
use CMS::Page(auto_deploy => 1);
This will avoid the performance hit of checking for the existence of a class' table.
At the moment all associations are implemented as unidirectional
Set associations using Set::Object
Tests are a bit sparse at the moment.
Only MySQL, PostgreSQL SQLite and DBM::Deep are supported currently. It should be fairly trivial to add support for the other RDBMS'
Special thanks to:
For educating me about meta-models and feedback.
For bug reports and patches, and his ongoing help with documentation, tests and good suggestions.
Class::DBI, Tangram, Class::Tangram, SQL::Abstract, Class::Data::Inheritable, Data::Types, DBM::Deep, DBI, ImA::DBI
Copyright (C) 2005 Richard Hundt <richard NO SPAM AT protea-systems.com>
Oryx is free software and may be used under the same terms as Perl itself.
1 POD Error
The following errors were encountered while parsing the POD:
You forgot a '=back' before '=head1'
To install Oryx, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Oryx
CPAN shell
perl -MCPAN -e shell install Oryx
For more information on module installation, please visit the detailed CPAN module installation guide.