NAME
Class::PObject::Driver::file - Default PObject driver
SYNOPSIS
pobject Person => {
columns => ['id', 'name', 'email']
datasource=> 'data'
};
DESCRIPTION
Class::PObject::Driver::file is a default driver used by Class::PObject. Class::PObject::Driver::file is a direct subclass of Class::PObject::Driver. Refer to its manual for more details.
The only required class property is columns. If driver is missing, Class::PObject will default to file automatically. If datasource is missing, the driver will default to your system's temporary directory, which is /tmp on most *nix systems, and C:\TEMP on Windows.
This data source is a folder in your operating system, inside which objects will be stored. Pobject will create a folder for each object type inside the datasource folder, and will store all the objects of the same type in their own folders.
SUPPORTED FEATURES
Class::PObject::Driver::file overrides following methods of Class::PObject::Driver
save()
load()
remove()
In addition to standard methods, it also defines following methods of its own. These methods are just private/utility methods that are not invoked by PObjects directly. But knowledge of these methods may prove useful if you want to subclass this driver to cater it to your needs.
load_by_id($self, $pobject_name, \%properties, $id)
is called from withinload()
method when an object is to be loaded by id. This happens if the pobject invokesload()
method with a single digit:$article = Article->load(443)
This is the most efficient way of loading objects using file driver.
Although the effect of saying
$article = Article->load({id=>443})
is the same as the previous example, the latter will bypass optimizer, thus will not invoke
load_by_id()
method.generate_id($self, $pobject_name, \%properties)
is called whenever a new object is to be stored and new, unique ID is to be generated._dir($self, $pobject_name, \%propertries)
is called to get the path to a directory where objects of this type are to be stored. If the directory hierarchy doesn't exist, it will create necessary directories automatically, assuming it has necessary permissions._filename($self, $pobject_name, \%properties)
is called to get a path to a file this particular object should be stored into._filename()
will call_dir()
method to get the object directory, and builds a filename inside this directory.freeze($self, \%data)
andthaw($self, $string)
are used to serialize and de-serialize the data to make it suitable for storing into disk. By defaultfreeze()
andthaw()
use Data::Dumper. If you want to use some other method, you can subclass Class::PObject::Driver::file and define your ownfreeze()
andthaw()
methods:# Inside Class/PObject/Driver/my_file.pm package Class::PObject::Driver::my_file; use base ('Class::PObject::Driver::file'); require Storable; sub freeze { my ($self, $data) = @_; return Storable::freeze($data) } sub thaw { my ($self, $string) = @_; return Storable::thaw($string) } 1; # Inside Article.pm, for example: package Article; pobject { columns => ['id', 'title', 'author', 'content'], driver => 'my_file' };
OBJECT STORAGE
Each object is stored as a separate file. File name pattern for each object file is defined in $Class::PObject::Driver::file::f
global variable, is is obj%05.cpo
by default, where %05
will be replaced with the id of the object, zeroes padded if necessary.
Note: extension '.cpo' stands for Class::PObject.
SERIALIZATION
Objects are serialized using standard Data::Dumper
ID GENERATION
file driver keeps its own record counter for generating auto-incrementing values for subsequent records more efficiently. Record counter is stored inside the object directory (_dir()
method returns the path to this folder) in a file called "counter.cpo".
WARNING
Removing counter.cpo from the directory will force PObject to reset object ids. This may be a problem if there already are objects in the directory, and they may be overridden by new ids. I realize this is a scary limitation, which will be eventually addressed.
In the meanwhile, just don't make habit of removing counter.cpo!
EFFICIENCY
Since the driver doesn't keep an index of any kind, the most efficient way of loading the data is by its id. A relatively simple load(undef, {limit=
n})> syntax is also relatively fast.
my $p = Person->load(451);
my @people = Person->load();
my @group = Person->load(undef, {limit=>100});
as load() becomes complex, the performance gets degrading:
my @people = Person->load({name=>"Sherzod"}, {sort=>'age', direction=>'desc', limit=>10, offset=>4});
To perform the above search, the driver walks through all the objects available in the datasource, pushes all the objects matching 'name="sherzod"' to the data-set, then, just before returning the data set, performs sort, limit and offset calculations.
As you imagine, as the number of objects in the datasource increases, this operation will become more costly.
SEE ALSO
Class::PObject, Class::PObject::Driver::mysql, Class::PObject::Driver::file
AUTHOR
Sherzod Ruzmetov <sherzodr@cpan.org>