File Coverage

blib/lib/SLOOPS.pm
Criterion Covered Total %
statement 6 6 100.0
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 8 8 100.0


line stmt bran cond sub pod time code
1             package SLOOPS;
2              
3 1     1   36294 use warnings;
  1         3  
  1         31  
4 1     1   5 use strict;
  1         3  
  1         127  
5              
6             =head1 NAME
7              
8             SLOOPS - Simple, Light, Object Oriented Persistence System .
9              
10             =head1 VERSION
11              
12             Version 0.01
13              
14             =cut
15              
16             our $VERSION = '0.01';
17              
18             =head1 DESCRIPTION
19              
20             SLOOPS is a lightweight Object Oriented persistence system.
21              
22             If you want to follow the tutorial, uncompress the distribution from command line !
23              
24             It has been designed with simplicity and reliability in mind. So you should expect:
25              
26             - VERY EASY AND QUICK implementation of your own datamodel.
27             - VERY EASY retrieving of your data.
28             - Some limitations that are negligable for 90% of cases !
29              
30             It has been tested in production environment for months, so you can relie on it !
31              
32             It allows to make objects persistents with just
33             a few lines of declarative code. It supports:
34              
35             - Inheritance
36             - Class polymorphism.
37             - Scalar attributes ( can be Object ! )
38             - SQL Free queries !
39             - MySQL database ( other ones in the future ).
40             - Optionnal caching based on Cache::FastMemoryCache .
41              
42             It doesn't support :
43              
44             - nonscalar attributes. So you have to do helper objects to support n-n relations . Is it so bad ?
45             - transaction . That's a serious issue. Will be implemented with other database support !
46            
47              
48              
49             =head1 TUTORIAL
50              
51             Here, you'll learn how to use SLOOPS to implement your own persistent datamodel.
52              
53             =head1 Datamodel.
54            
55             For the purpose of this tutorial, we'll use a very simple datamodel. It is composed of Vehicules
56             which can be Cars or Planes , Persons who owns vehicules. A vehicule can be driven by: its owner but
57             also by other persons.
58              
59             So we got:
60             Vehicule - own by -> one person.
61             Car - Is a -> Vehicule ( inheritance )
62             Plane - Is a -> Vehicule ( inheritance )
63             Vehicule - driven by -> several persons
64             Person - drives -> several vehicules Here we'll need a helper class to represent this n-n relation.
65              
66             Attributes of classes are obvious !
67              
68             =head2 Implementation.
69              
70             First, let's implement the Person class !
71              
72             package SLOOPS::Tut::Person ;
73            
74             use base qw/Class::AutoAccess/ ; # for easy attribute access.
75              
76             # SLOOPS PART
77            
78             our $PERSIST = {
79             fields => {
80             'firstName' => undef , # DEFAULT type will be used in database.
81             'lastName' => undef
82             }
83             } ;
84              
85             # END OF SLOOPS PART
86            
87             sub new{
88             my ($class) = @_ ; # A persistant class MUST implement a no parameters constructor !
89             my $self = {
90             'firstName' => undef ,
91             'lastName' => undef ,
92             'non_perst' => undef # This attribute will not be persistent !!
93             };
94             return bless $self, $class ;
95             }
96            
97             1;
98              
99             So you understood how it works !
100              
101             All you have to do to turn a class persistent is :
102            
103             - implement a void parameter contructor named 'new' .
104             - set the $PERSIST global variable of your class to indicate what to persist !
105              
106             Now, we're ready to implement our Vehicule class !
107              
108             package SLOOPS::Tut::Vehicule ;
109            
110             use base qw/Class::AutoAccess/ ;
111              
112             our $PERSIST = {
113             'fields' => {
114             'nbDoors' => [ 'INT' , 0 ], # Here we use the possibility to control how the attribut will be
115             # stored and what is its default value
116             'nbWheels' => [ 'INT' , 1 ]
117             },
118             'references' => {
119             'owner' => 'SLOOPS::Tut::Person' # Owner will be a reference on a person !!
120             }
121             };
122            
123             sub new{
124             my ($class) = @_ ;
125             my $self = {
126             'nbDoors' => undef ,
127             'nbWheels' => undef,
128             'owner' => undef
129             };
130             return bless $self, $class ;
131             }
132              
133              
134             1;
135              
136             Here is a new concept:
137              
138             The reference . It is used to make persistent the composition of object.
139             In this case, it means the vehicule will hold a reference on its owner object. And that will be persistent!
140              
141             Ok now let's implement our subclasses of Vehicules (Car and Plane):
142              
143             package SLOOPS::Tut::Car ;
144            
145             use base qw/SLOOPS::Tut::Vehicule/ ;
146            
147             our $PERSIST = {
148             'base' => 'SLOOPS::Tut::Vehicule' ,
149             'fields' => {
150             'body' => undef
151             }
152             };
153              
154            
155             sub new{
156             my ($class) = @_ ;
157             my $self = $class->SUPER::new();
158            
159             $self->nbWheels(4) ;
160             $self->{'body'} = undef ; # van, convertible , coupe ...
161            
162             return bless $self , $class ;
163            
164             }
165              
166             1;
167              
168             Just say 'base' => 'SLOOPS::Tut::Vehicule' , add the added field and that's all !!
169              
170             Write Plane by yourself !! (or pick the code in SLOOPS/Tut directory ..)
171              
172             To end with datamodel, let's implement the WhoDrivesWhat class (remember our n-n relation ! ).
173              
174             package SLOOPS::Tut::WDW ;
175            
176             use base qw/Class::AutoAccess/ ;
177            
178             our $PERSIST = {
179             'references' =>
180             {
181             'who' => 'SLOOPS::Tut::Person' ,
182             'what' => 'SLOOPS::Tut::Vehicule' # Polymorphism support !!
183             }};
184              
185             sub new{
186             my ($class) = @_ ;
187              
188             my $self = {
189             'who' => undef,
190             'what' => undef
191             };
192             return bless $self, $class ;
193             }
194             1;
195              
196             Ok, that's all for our Datamodel. As you see, you need a very few lines to implement each class.
197             Almost each line of code contains usefull information.
198             Implementing and testing an object datamodel is a matter of hours instead of days !
199              
200             =head2 MODEL DEPLOYMENT
201              
202             Now, our model is ok, we need to deploy it in a database in order to be able to use it.
203             All you have to do is to connect the system to the database. Tell him what class are persistent, and
204             ask for deployement.
205              
206             The following code should go in the deployment script of your application:
207              
208             # INIT
209             use DBI ;
210              
211             use SLOOPS::Factory { debug => 0 } ;
212             use SLOOPS::SchemaGenerator { debug => 0 };
213             use SLOOPS::DbDriverMySQL ;
214            
215             # CONNECTING TO DB
216             my $dbDriver = SLOOPS::DbDriverMySQL->new();
217             my $dbh = DBI->connect('dbi:mysql:test_perst', 'perlu', 'perl',
218             { RaiseError => 1, AutoCommit => 0 }) || die "No connect : $!";
219              
220             $dbDriver->dbh($dbh);
221              
222             my $g = SLOOPS::SchemaGenerator->instance();
223             $g->dbDriver($dbDriver);
224              
225             SLOOPS::Factory->instance()->dbDriver($dbDriver);
226             # END OF INIT
227              
228             # REGISTERING CLASSES
229             # Register the class(es) to handle.
230             $g->addClass('SLOOPS::Tut::Person');
231             $g->addClass('SLOOPS::Tut::Car');
232             $g->addClass('SLOOPS::Tut::Plane');
233             $g->addClass('SLOOPS::Tut::WDW');
234            
235             # THIS IS THE IMPLEMENTATION OF THE SCHEMA !!
236             $g->updateSchema(1);
237              
238             That's all for model deployment !
239             Note that the code between #INIT and #END OF INIT have to be used ONCE in the init phase
240             of your application.
241              
242             You can find this deployement script into the deployTut.pl script of the distribution.
243              
244             =head2 USING YOUR SLOOPS model implementation.
245              
246             In this section, we'll see how to use SLOOPS to make new instance of objects, to retrieve
247             instances and to navigate throu references. We'll only give simple use.
248              
249             See SLOOPS::Factory documentation for complete doc about all possible functions you can use
250             to interact with your model.
251              
252             Let's say we got $f, a factory instance (remember to run the init code first !):
253              
254             $f = SLOOPS::Factory->instance();
255              
256             Now, we can create a person object !
257              
258             my $p = SLOOPS::Tut::Person->new();
259             $p->firstName('John');
260             $p->lastName('Doe');
261              
262             To make it persistant:
263            
264             $f->saveObject($p) ;
265              
266              
267             You also directly create (or find if it allready exists) a person object which is allready persistent:
268              
269             my $p2 = $f->findOrCreate('SLOOPS::Tut::Person' ,
270             { 'firstName' => [ '=' , 'Bruce' ],
271             'lastName' => [ '=' , 'Wayne' ]
272             });
273              
274             This is one of my favorite features !
275              
276             Now, let's create a car that belongs to bruce wayne !
277              
278             my $c = $f->findOrCreate('SLOOPS::Tut::Car' ,
279             {
280             'nbDoors' => [ '=' , 2 ],
281             'nbWheels' => [ '=' , 4 ],
282             'owner' => $p2 ,
283             'body' => [ '=' , 'batcar' ]
284             });
285              
286             We can also cascade many findOrCreate to create at the same time the vehicule and the owner...
287              
288              
289             my $p = $f->findOrCreate('SLOOPS::Tut::Plane' ,
290             {
291             'nbDoors' => [ '=' , 1 ],
292             'nbWheels' => [ '=' , 3 ],
293             'owner' => $f->findOrCreate('SLOOPS::Tut::Person' ,
294             { 'firstName' => [ '=' , 'Pete' ],
295             'lastName' => [ '=' , 'Mitchell' ]
296             })
297            
298             ,
299             'nbWings' => [ '=' , 2 ]
300             });
301            
302              
303             These are the two main possibilities to create object.
304              
305             To retrieve them, there's a lot of possibilities. Let's stay simple:
306              
307             my $vehicules = $f->seekObjects('SLOOPS::Tut::Vehicule', {
308             'nbDoors' => [ '>' , 0 ] });
309            
310             foreach my $v ( @$vehicules ){
311             print 'Type: '.ref($v)."\n"; # CLASS POLYMORPHISM !!
312             print 'Owner: '.$v->owner_O()->firstName() ."\n" ; # Object composition.
313             }
314              
315             The important point is the 'owner_O' method of the retrieved vehicule.
316             This is an auto generated method that allows you to access the object references by
317             the attribute 'owner' of the vehicule class.
318              
319             These method 'attribute'_O are automatically generated for all reference attributes !
320             So you can use them to access object directly without making any other request.
321              
322             This usage code is available in the useTut.pl script given in the distribution !
323              
324              
325             There's many things you can do with SLOOPS. To see all possibility, please refer to
326             the SLOOPS::Factory documentation !!
327              
328              
329             =head1 REFERENCE
330              
331             =head2 SYNTAX of $PERSIST
332              
333              
334             Persist should look like that :
335              
336             $PERSIST = {
337             'base' => 'AObjectClass' , # OPTIONNAL
338             fields => { # OPTIONNAL
339             'f1' => undef , # DEFAULT SQL TYPE AND DEFAULT VALUE GIVEN BY SQL DRIVER
340             'f2' => [ 'NUMBER', 0 ] ,# CHOOSEN TYPE AND CHOOSEN DEFAULT
341             ....
342             },
343             references => { # OPTIONNAL
344             'ref1' => 'AnObjectClass', # A Reference on another object of given class or subclasses of it !
345             ...
346             }
347             };
348              
349              
350              
351              
352             =head1 AUTHOR
353              
354             Jerome Eteve, C<< >>
355              
356             =head1 BUGS
357              
358             Please report any bugs or feature requests to
359             C, or through the web interface at
360             L.
361             I will be notified, and then you'll automatically be notified of progress on
362             your bug as I make changes.
363              
364             =head1 ACKNOWLEDGEMENTS
365              
366             =head1 COPYRIGHT & LICENSE
367              
368             Copyright 2005 Jerome Eteve, all rights reserved.
369              
370             This program is free software; you can redistribute it and/or modify it
371             under the same terms as Perl itself.
372              
373             =cut
374              
375             1; # End of SLOOPS