> this is my first time using Perl as anything other than
a glorified awk.
Well, I hope this is a good beginning for you. Thanks for
taking a look at Object::InsideOut.
First, let's tackle the following bug:
$test1[$$self] = @$tmpref;
An array in a scalar context returns its 'length'. Thus,
you end up storing the number 3, which is not what you want.
What you want is to store the array ref itself in the field.
Thus, for the fix, you have several options: You can either
store the input directly with:
$test1[$$self] = $tmpref;
or you can make a copy, and then store that:
my @copy = @$tmpref;
$test1[$$self] = \@copy;
Since your input is assigned to $arrref, the latter might be
preferable if your code will be making any changes to the
the array ref's contents via $arrref. If not, the former is
simpler.
However, the option that is preferable to the above is to
use the 'set' method:
$self->set(\@test1, $tmpref);
This has the same effect as the first example above with one
crucial difference: If your code is being used in a
threads::shared environment, the 'set' method handles all
the details of making a shared copy of the data you're going
to store in your fields.
Now, as to your question, I'll be working with a slightly
modified version of your example. Most notably, I'll be
using Test::More because it makes it easy to show test
results.
The first thing you should try is to let Object::InsideOut
do the menial work for you. Consider your :Init subroutine:
All it does is store the input into the field. By
uncommenting the 'Field' parameter in your :InitArgs, you
can have Object::InsideOut automatically do this for you
such that you don't even need an :Init subroutine at all:
use warnings;
use strict;
use Test::More 'no_plan';
package Hashtest; {
use Object::InsideOut;
my @data :Field('Standard' => 'data');
my %init_args :InitArgs = (
'DATA' => {
'Regex' => qr/^data/i,
'Type' => 'ARRAY',
'Field' => \@data,
},
);
}
package main;
my $input = [ "hunger", "pain", "misery" ];
my $obj = Hashtest->new('data' => $input);
my $output = $obj->get_data();
is_deeply($input, $output => 'Equality for all');
exit(0);
Note that I added accessor generation parameters to the
:Field attribute so that the data could be accessed via the
object.
Here's the same example with the :Init subroutine added back
in, and using the 'set' method as discussed above:
use warnings;
use strict;
use Test::More 'no_plan';
package Hashtest; {
use Object::InsideOut;
my @data :Field('Standard' => 'data');
my %init_args :InitArgs = (
'DATA' => {
'Regex' => qr/^data/i,
'Type' => 'ARRAY',
},
);
sub _init :Init
{
my ($self, $args) = @_;
if (exists($args->{'DATA'})) {
$self->set(\@data, $args->{'DATA'});
}
}
}
package main;
my $input = [ "hunger", "pain", "misery" ];
my $obj = Hashtest->new('data' => $input);
my $output = $obj->get_data();
is_deeply($input, $output => 'Equality for all');
exit(0);
Since you did not make the 'DATA' parameter mandatory, the
:Init subroutine needs to check for existance prior to
trying to store the data.
Hope this answered your question adequately.
|