NAME
Su - A simple application layer to divide and integrate data and processes in the Perl program.
SYNOPSIS
my $su = Su->new;
my $proc_result = $su->resolve('process_id');
print $proc_result;
DESCRIPTION
Su is a simple application framework that works as a thin layer to divide data and process in your Perl program. This framework aims an ease of maintenance and extension of your application.
Su is a thin application layer, so you can use Su with many other frameworks you prefer in many cases.
Note that Su framework has nothing to do with unix su
(switch user) command.
Prepare Data and Process file
Su provides the method to generate the template of Model and Process. You can use method generate()
like the following:
perl -MSu -e 'Su::generate("Pkg::SomeProc")'
Then, the file Pkg/SomeProc.pm and Pkg/SomeModel.pm should be generated.
Now describe your data to the $model
field of the generated Model file.
my $model=
{
field_a =>'value_a'
};
And describe your process code to the process
method defined in the generated Process file like the following:
sub process{
my $self = shift if ref $_[0] eq __PACKAGE__;
my $param = shift;
my $ret = "param:" . $param . " and model:" . $model->{field_a};
return $ret;
}
Integrate Model and Process
Su integrates Model and Processes using the definition file. To generate the definition file, type the following command.
perl -MSu -e 'Su::gen_defs()'
Then describe your setting to the $defs
field defined in the generated Defs.pm file.
my $defs =
{
some_entry_id =>
{
proc=>'Pkg::SomeProc',
model=>'Pkg::SomeModel',
},
};
You can also generate Defs.pm using the generate
method by passing the parameter 1
as a second parameter.
perl -MSu=base,lib -e 'Su::generate("Pkg::SomeProc", 1)'
Then the file Defs.pm will be generated with Model and Process file.
Run the process using Su
You can call the process via Su by passing the entry id which defined in the definition file Defs.pm.
my $su = Su->new;
my $result = $su->resolve('some_entry_id');
To pass the parameters to the process
method in Process, then pass the additional parameter to the resolve
method.
my $result = $su->resolve('some_entry_id', 'param1');
Other features Su provides
Logging and string template are the feature su provides for convinience. These features are frequently used in many kinds of applications and you can use these features without any other dependencies. Surely you can use other modules you prefer with Su framework.
Additional usage - Filters
The map, reduce and scalar filters can be defined in the definition file.
These filters are Perl module which has the method for filtering the result of the process. (In case of map
filter, method name is map_filter
.) You can chain filter modules. The following code is a sample definition which uses these filters.
my $defs =
{
some_proc_id =>
{
proc=>'MainProc',
model=>'Pkg::MainModel',
map_filter=>'Pkg::FilterProc', # or ['Filter01','Filter02']
reduce_filter=>'Pkg::ReduceProc', # reduce filter can only apply at once.
scalar_filter=>'Pkg::ScalarProc', # or ['Filter01','Filter02']
}
};
The filters Su recognizes are the followings.
- map_filter
-
The perl module which has
map_filter
method. The parameter of this method is an array which is a result of the 'process' method of the Process or the chained map filter. Themap_filter
method must return the array data type. - reduce_filter
-
The perl module which has
reduce_filter
method. The parameter of this method is an array which is a result of the 'process' method of the Process. If the map filters are defined in theDefs.pm
, then the map_filters are applied to the result of the process before passed to the reduce filter. Thereduce_filter
method must return the scalar data type. Note that this method can't chain. - scalar_filter
-
The perl module which has
scalar_filter
method. The parameter of this method is a scalar which is a result of the 'process' method of the Process. If themap_filters
andrecude_filters
are defined in theDefs.pm
, then these filters are applied to the result of the process before passed to the scalar filter.The
scalar_filter
method must return the scalar data type.
ATTRIBUTES
$MODEL_LOCALE
Set the locale string like 'ja_JP' to load locale specific Model module. Locale specific Model has the postfix in it's name like 'Pkg::ModelName__ja_JP'.
Then you should set the locale like this.
$Su::MODEL_LOCALE = 'ja_JP';
$MODEL_KEY_PREFIX
The hash reference which contains the key prefixes of the Model. The key of this hash is a name of the model to apply this prefix.
$MODEL_KEY_PREFIX = {
'pkg::SomeModel'=>'pre1',
};
In this example, the key string 'pre1_key1' defined in 'pkg::SomeModel' is automatically converted to 'key1'. So you can access customized value using key 'key1'.
If the modified key is not exist, then the value of original key should used.
$MODEL_KEY_POSTFIX
The hash reference which contains the key postfixes of the Model. The key of this hash is a name of the model to apply this postfix.
This variable work same as $MODEL_KEY_PREFIX.
METHODS
- import()
-
use Su base=>'./base', proc=>'tmpls', model=>'models', defs=>'defs';
If you want to specify some parameters from the command line, then it becomes like the following.
perl -Ilib -MSu=base,./base,proc,tmpls,defs,models -e '{print "do some work";}'
- setup()
-
Instead of loading the definition form the Definition file, this method set the definition directly.
Su::setup( menu =>{proc=>'MenuTmpl', model=>qw(main sites about)}, book_comp =>{proc=>'BookTmpl', model=>'MenuModel'}, menuWithArg =>{proc=>'MenuTmplWithArg', model=>{field1=>{type=>'string'},field2=>{type=>'number'}}}, );
- new()
-
Instantiate the Su instance. To make Su instance recognize the custom definition module, you can pass the package name of the definition file as a parameter.
my $su = Su->new;
my $su = Su->new('Pkg::Defs');
my $su = Su->new(defs_module=>'Pkg::Defs');
- resolve()
-
Find the passed id from the definition file and execute the corresponding Process after the injection of the corresponding Model to the Process.
An example of the definition in Defs.pm is like the following.
my $defs = { entry_id => { proc=>'Pkg::SomeProc', model=>'Pkg::SomeModel', }, };
Note that
proc
field in the definition file is required, butmodel
field can omit. To execute the process descired in this example, your code will become like the following.my $ret = $su->resolve('entry_id');
If you pass the additional parameters to the resolve method, these parameters are passed to the
process
method of the Process.my $ret = $su->resolve('entry_id', 'param_A', 'param_B');
If the passed entry id is not defined in Defs file, then the error is thorwn.
Definition can be also specified as a parameter of the
resolve
method like the following.$su->resolve({ proc=>'MainProc', model=>['Model01','Model02','Model03'], }); $su->resolve( { proc => 'Sample::Procs::SomeModule', model => { key1 => { 'nestkey1' => ['value'] } }, }, 'arg1', 'arg2');
Optional Usage - Model Definition
This method works differently according to the style of the model definition.
If the
model
field is a string, then Su treat it as a name of the Model, load it's class and set it'smodel
field to the Process.some_entry_id =>{proc=>'ProcModule', model=>'ModelModule'},
If the
model
field is a hash, Su set it's hash to themodel
field of the Process directly.some_entry_id =>{proc=>'ProcModule', model=>{key1=>'value1',key2=>'value2'}},
If the
model
field is a reference of the string array, then Su load each element as Model module and execute Process with each model.some_entry_id =>{proc=>'TmplModule', model=>['ModelA', 'ModelB', 'ModelC']},
In this case, Process is executed with each Model, and the array of each result is returned.
Optional Usage - Filters
If a definition has any filter related fields, then these filter methods are applied before Su return the result of the process method. The module specified as a filter must has the method which corresponds to the filter type. About usable filter types, see the section of
map_filter
,reduce_filter
,scalar_filter
.These filter methods receive the result of the process or previous filter as a parameter, and return the filtered result to the caller or next filter.
Following is an example of the definition file to use post filter.
my $defs = { exec_post_filter => { proc=>'MainProc', model=>['Model01','Model02','Model03'], post_filter=>'FilterProc' },
Multiple filters can be set to the definition file.
exec_post_filter_chain => { proc=>'MainProc', model=>['Model01','Model02','Model03'], post_filter=>['FilterProc1', 'FilterProc1'] } };
An example of the
map_filter
method in the filter class is the following. Themap_filter
receives an array of previous result as a parameter and return the result as an array.sub map_filter { my $self = shift if ref $_[0] eq __PACKAGE__; my @results = @_; for (@results) { # Do some filter process. } return @results; }
An example of the
reduce_filter
method in the filter class is the following. Thereduce_filter
receives an array as a parameter and return the result as a scalar.sub reduce_filter { my $self = shift if ref $_[0] eq __PACKAGE__; my @results = @_; # For example, just join the result and return. return join( ',', @results ); }
An example of the
scalar_filter
method in the filter class is the following. Thescalar_filter
receives a scalar as a parameter and return the result as a scalar.sub scalar_filter { my $self = shift if ref $_[0] eq __PACKAGE__; my $result = shift; # Do some filter process to the $result. return $result; }
This method change the Model file to load by the specified locale.
If you specify the resource locale to $Su::MODEL_LOCALE, this method load locale specific Model automatically, and locale specific Model is not exist, then this method tring to load default Model.
Set the locale variable like the following:
$Su::MODEL_LOCALE = 'ja_JP';
The name of locale specific Model is like the following:
pkg::SomeModel__ja_JP
And the file name becomes like this.
pkg/SomeModel__ja_JP.pm
- get_proc()
-
This function is just a synonym of the method get_instance.
-
Just return the instance of the Process which defined in Defs file. Model data is set to that returned Process.
my $proc = $su->get_instance('main_proc');
- get_inst()
-
This function is just a synonym of the method get_instance.
- retr()
-
This function is just a synonym of the method get_instance.
- inst()
-
This function is just a synonym of the method get_instance.
- init()
-
Generate the initial files at once. The initial files are composed of Defs, Model and Process module.
Su::init('PkgName');
This method can be called from command line like the following:
perl -MSu=base,base/directory -e 'Su::init("Pkg::SomeModule")'
- gen_model()
-
Generate a Model file.
Su::gen_model("SomePkg::SomeModelName") perl -MSu=base,./lib/ -e 'Su::gen_model("Pkg::ModelName")'
- gen_proc()
-
Generate a Process file.
perl -MSu=base,./lib/ -e 'Su::gen_proc("Pkg::TestProc")'
- generate()
-
Generate a pair of Process and Model file.
my $su = Su->new; $su->generate('pkg::SomeProc');
This example generates
pkg/SomeProc.pm
andpkg/SomeModl.pm
.You can use this method from the commandline.
perl -MSu=base,lib -e 'Su::generate("Pkg::SomeProc", 1)' perl -MSu=base,lib -e 'Su::generate("Pkg::SomeProc", "Defs::MyDefs")'
If the second parameter is specified, the Defs file will generated.
- gen_defs()
-
Generate a definition file.
perl -MSu=base,./lib/ -e 'Su::gen_defs()'
You can specify the package name of the definition file as a parameter.
gen_defs('Defs::Defs');
Also you can specify other parameters as a hash.
gen_defs(name=>'Defs::Defs', package=>'pkg', proc=>'MyProc', model=>'MyModel', just_add_entry_if_defs_already_exist => 1, use_proc_name_as_entry_id => 1)
param use_proc_name_as_entry_id: Set the proc name as entry id instead of default id 'main'.
param just_add_entry_if_defs_already_exist: If the specified Defs file is already exist, then add the entry to that Defs file.
return: 1: If generation success. 0: If the Defs file already exists.
SEE ALSO
Su::Process,Su::Model,Su::Template,Su::Log
AUTHOR
lottz <lottzaddr@gmail.com>
LICENSE
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
1 POD Error
The following errors were encountered while parsing the POD:
- Around line 914:
Expected text after =item, not a bullet