I'm currently delegating the builder method to all of the objects that extend one of my base classes. The problem that I'm facing is I need all of the objects to either read an attribute of itself or be passed in a value.
# In Role:
has 'const_string' => (
isa => 'Str',
is => 'ro',
default => 'test',
);
has 'attr' => (
isa => 'Str',
is => 'ro',
builder => '_builder',
);
requires '_builder';
# In extending object - desired 1
sub _builder {
my ($self) = shift;
# $self contains $self->const_string
}
# In extending object - desired 2
sub _builder {
my ($arg1, $arg2) = @_;
# $args can be passed somehow?
}
Is this currently possible or am I going to have to do it some other way?
You can't pass arguments to attribute build methods. They are called automatically by Moose internals, and passed only one argument -- the object reference itself. The builder must be able to return its value based on what it sees in $self
, or anything else in the environment that it has access to.
What sort of arguments would you be wanting to pass to the builder? Can you instead pass these values to the object constructor and store them in other attributes?
# in object #2:
has other_attr_a => (
is => 'ro', isa => 'Str',
);
has other_attr_b => (
is => 'ro', isa => 'Str',
);
sub _builder
{
my $self = shift;
# calculates something based on other_attr_a and other_attr_b
}
# object #2 is constructed as:
my $obj = Class2->new(other_attr_a => 'value', other_attr_b => 'value');
Also note that if you have attributes that are built based off of other attribute values, you should define them as lazy
, otherwise the builders/defaults will run immediately on object construction, and in an undefined order. Setting them lazy will delay their definition until they are first needed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With