Reputation: 5856
Again once have a problem with the Moose object model. I'm not sure about the posting here or better to "codereview" - trying here first... ;)
Region
.Spot
(s).name
and some Entries
.id
, content
, flag
.The API should work as next:
my $region = Region->new; #create a Region
my $sx = $region->spot('x'); #return the Spot with a name 'x'
#if the spot with a name 'x' doesn't exists, create it
$sx->add(id => 'id1', content => 'content1', flag => 'f1'); #add a new Entry to Spot 'x'
$sx->add(id => 'id2', content => sub { return "string" }, flag => 'f2');#add another Entry
$sx->render; # render the "spot" - do some operations on array of Entries
What I already have - sorry for the long sources - i shortened them to smallest working packages.
First - have a simple class for the "Entries".
package Region::Entry;
use namespace::sweep;
use Modern::Perl;
use Moose;
has 'id' => (is => 'rw', isa => 'Str');
has 'content' => (is => 'rw', isa => 'Str|CodeRef');
has 'flag' => (is => 'rw', isa => 'Str');
__PACKAGE__->meta->make_immutable;
1;
class for the Region - has only one HashRef for storing Spots by spotname (as keys)
package Region;
use namespace::sweep;
use Modern::Perl;
use Moose;
use Method::Signatures::Simple;
use Region::Spot;
has 'spots' => (
traits => ['Hash'],
is => 'rw',
isa => 'HashRef[Region::Spot]',
default => sub { {} },
handles => {
set_spot => 'set',
get_spot => 'get',
spot_exists => 'exists',
},
);
method spot {
my $name = shift;
return undef unless $name;
$self->set_spot($name => Region::Spot->new()) unless $self->spot_exists($name);
return $self->get_spot($name);
}
__PACKAGE__->meta->make_immutable;
1;
finally class for the Spots
package Region::Spot;
use Modern::Perl;
use namespace::sweep;
use Moose;
use Method::Signatures::Simple;
use Region::Entry;
has 'entries' => (
traits => ['Array'],
is => 'rw',
isa => 'ArrayRef[Region::Entry]',
default => sub { [] },
handles => {
add_entry => 'push',
},
);
#PROBLEM HERE - HOW TO IMPLEMENT THIS for allow attributes as in the above API
#so add(id=>'id', content => 'xxxx', flag => 'f');
#with correct attribute checking????
method add {
#$self->add_entry....
}
method render {
#...
return "rendered entries";
}
__PACKAGE__->meta->make_immutable;
1;
So, having problem with implementing the add
API. See the comments above...
$sx->add(id => 'id1', content => 'content1', flag => 'f1'); #add a new Entry to Spot 'x'
My object model or it's implementation is probably wrong, because the i have the add
method on class where haven't defined the types ... or don't know ...
This is my problem everytime, when creating anything new. I know "how to use Moose" (i'm not an expert, but knowing the basics) - but have problem define the right classes... :(
I hope the above make sense... and sry for the long post.
Upvotes: 3
Views: 727
Reputation: 924
Warning: untested code
If you are intent on the API being set that way, you can pass the attributes through to new
when creating your Region::Entry
method add {
my %params = @_;
$self->add_entry( Region::Entry->new(\%params) );
}
Additionally, you could
$sx->add( Region::Entry->new( { id => ..., } );
.
.
.
method add {
my $self = shift;
$self->add_entry( shift );
}
Upvotes: 1
Reputation: 66978
I might be missing some subtle detail of your question, but why not just unpack the arguments in your add
method and create a new Entry
?
method add {
$self->add_entry( Entry->new( @_ ) );
}
Upvotes: 1