NAME
Backed_Objects - Create static files from a database.
VERSION
Version 1.13
SYNOPSIS
Create static files from a database. Update the files every time when you update the database.
It can be used with any kind of database, for example SQL databases, Berkeley databases, data stored in .ini files, etc.
USAGE OF THE CLASS
The class Backed_Objects
is an abstract base class and you need to derive your class from it. For further suppose you developed a class HTML_DB
derived from Backed_Objects
. We will call HTML (for example) files which are updated by this module the view.
All methods can be called either as object methods or as class methods.
Calling these as class methods may be convienient when you do not need to specify additional parameters to be put into an object.
Thus the following alternatives are possible:
HTML_DB->output_all_and_order;
or
my $obj = HTML_DB->new;
$obj->output_all_and_order;
Examples below assume that you are familiar with SQL and DBI
module.
Database update methods
The class Backed_Objects
offers you flexibility on the way how you update your database.
One variant is to override do_insert
, do_update
, do_delete
, post_process
methods, so that they will update your database when insert
, update
, delete
methods are called.
The other variant is to update the database yourself and afterward to call insert
, update
, delete
which will call the default do-nothing do_insert
, do_update
, do_delete
, post_process
methods.
The object and the ID
A database stores objects, every object stored in a database has an ID. An object may be without an ID when it is not yet stored into the DB, but you must assign an ID to an object when you store it in the DB, either by overriding do_insert
method which should set the object ID or yourself in your own code (without overriding do_insert
). HTML_DB
must have id
method which receives an object and return its ID.
The interface of this module does not specify what objects are. Objects may be hashes or any other data structures.
Every object inserted into the database has ID (which may be a natural number, but is not required to be a number).
Sometimes you may want the objects and IDs to be the same. For example, it is often OK for an object and an ID to be a row ID in a SQL database. Or you may want an object to be a hash representing a row in an SQL DB.
Sometimes a middle solution is fit: Store an object as a hash with some values from the database and read the rest values from the DB when needed, using the ID stored in the object.
An other possibililty for an object is to be a hash based on user input in a HTML form.
METHODS
id
This abstract (not defined in Backed_Objects
method) must be defined to return the ID of an object.
Examples:
sub id {
my ($self, $obj) = @_;
return $obj->{id};
}
or
# Objects are simple IDs
sub id {
my ($self, $obj) = @_;
return $obj;
}
all_ids
This abstract (not defined in Backed_Objects
method) must return a list of all IDs in the database.
sub all_ids {
my ($self) = @_;
return @{ $dbh->selectcol_arrayref("SELECT id FROM table") };
}
do_select
This abstract method should return an object from the DB having a given ID.
sub do_select {
my ($self, $id) = @_;
return $dbh->selectrow_hashref("SELECT * FROM table WHERE id=?", undef, $id);
}
or
# Objects are simple IDs
sub do_select {
my ($self, $id) = @_;
return $id;
}
select
This method returns an object from the DB or undef
if the ID is absent (undefined or zero).
See its implementation:
sub select {
my ($self, $id) = @_;
return undef unless $id;
return $self->do_select($id);
}
do_insert, do_update, do_delete, post_process
By default these methods do nothing. (In this case you need to update database yourself, before calling insert
, update
, or delete
methods.)
You may override these methods to do database updates:
sub do_insert {
my ($self, $obj) = @_;
my @keys = keys %$obj;
my @values = values %$obj;
my $set = join ', ', map { "$_=?" } @keys;
$dbh->do("INSERT table SET $set", undef, @values);
$obj->{id} = $dbh->last_insert_id(undef, undef, undef, undef);
}
sub do_update {
my ($self, $obj) = @_;
my @keys = keys %$obj;
my @values = values %$obj;
my $set = join ', ', map { "$_=?" } @keys;
$dbh->do("UPDATE table SET $set WHERE id=?", undef, @values, $obj->{id});
}
sub do_delete {
my ($self, $id) = @_;
$dbh->do("DELETE FROM table WHERE id=?", undef, $id);
}
sub post_process {
my ($self, $obj) = @_;
...
}
do_insert
should set object ID after it is saved into the database.
post_process
is called by insert
after the object is inserted into the database (and the object ID is set). It can be used for amending the object with operations which require some object ID, for example for uploading files into a folder with name being based on the ID.
post_process
is also called by update
.
outputter
This method should return a value used to output a view of the DB (for example it may be used to output HTML files and be a hash whose values are HTML templates).
Example:
use File::Slurp;
sub outputter {
my ($self) = @_;
my $template_dir = "$ENV{DOCUMENT_ROOT}/templates";
return { main_tmpl => read_file("$template_dir/main.html"),
announce_tmpl => read_file("$template_dir/announce.html") };
}
The default implementation returns undef
.
insert, update, delete
HTML_DB->insert($obj);
HTML_DB->update($obj);
HTML_DB->delete($id);
These functions update the view based on the value $obj
from the DB. They are to be called when an object is inserted, updated, or deleted in the DB.
If you've overridden the do_insert
, do_update
, or do_delete
methods, then insert
, update
, or delete
methods update the database before updating the view.
Note that insert
methods calls both on_update
and on_insert
methods (as well as some other methods, see the source).
insert
and update
also call post_process
.
update
also calls before_update
before calling do_update
. The before_update
method can be used to update the data based on old data in the DB, before the DB is updated by do_update
.
on_update
on_update
method it called when an object in the database is updated or after a new object is inserted.
By default on_update
calls the output
method to update the view of the object.
on_insert, on_delete, on_order_change, before_update
sub on_insert {
my ($self, $obj) = @_;
...
}
sub on_delete {
my ($self, $id) = @_;
...
}
sub on_order_change {
my ($self) = @_;
...
}
sub before_update {
my ($self, $obj) = @_;
...
}
These methods (doing nothing by default) are called correspondingly when:
- inserting a new object into the database;
- deleting an object from the database;
- changing order of objects in the database (including the case of inserting a new object).
- before calling
do_update
to update the database.
By default these methods do nothing.
You may update your view in your overrides of these methods.
before_update
is called by update
(but not by insert
) before updating the DB with do_update
.
on_any_change
sub on_any_change {
my ($self) = @_;
...
}
This method is called after every change of the database, for example, after insertion, deletion, update, etc.
do_output
sub do_output {
my ($self, $outputter, $obj) = @_;
...
}
This is the main method to output your files (the view).
It receives the object and the outputter returned by the outputter
method.
order_change
HTML_DB->order_change;
Call order_change
after you changed the order of objects in the database (but not after calling insert
or delete
method which call order_change
automatically).
output_by_id
An internal function.
output_all
HTML_DB->output_all;
HTML_DB->output_all_and_order;
output_all
updates the entire set of your files based on the data in the DB.
output_all_and_order
additionally updates data dependent on the order of objects in the DB.
Use these methods to update your all files (for example, after your template changed).
save
HTML_DB->save($obj);
This saves an object into the DB: updates it if it is already in the DB (has an ID) or inserts it into the DB if it has an undefined ID.
The actual code:
sub save {
my ($self, $obj) = @_;
if($self->id($obj)) {
$self->update($obj);
} else {
$self->insert($obj);
}
}
output
An internal function.
AUTHOR
Victor Porton, <porton@narod.ru>
BUGS
Please report any bugs or feature requests to bug-backed_objects at rt.cpan.org
, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Backed_Objects. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
In the current version of Backed_Objects
there are no provision for passing file handles for example got from a HTML form with a file
control. A complexity is that usually to upload a file we need to already know the ID of a row in a database what is possible only after inserting into the DB. Your suggestions how to deal with this problem are welcome.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Backed_Objects
You can also look for information at:
RT: CPAN's request tracker
AnnoCPAN: Annotated CPAN documentation
CPAN Ratings
Search CPAN
LICENSE AND COPYRIGHT
Copyright 2011 Victor Porton.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.