I have a filename attribute that has attached validation. Now when the filename isn't specified during construction I want to read it from a configuration file.
subtype 'filename'
=> as 'Str'
=> where { -r $_ }
=> message { "$_ is not a readable file" };
has 'students_file' => ( is => 'rw', isa => 'filename', default => '' );
has 'teach开发者_Go百科ers_file' => ( is => 'rw', isa => 'filename', default => '' );
The issue is that BUILD
seems to be run after the validation occurs. All examples of BUILDARGS
seem to handle a different way of constructing the object.
So where should I read the configuration and set the attribute?
Give teachers_file
and students_file
builder
methods (or inline default
subs) that set them from the config file. The builder will only run if those attributes aren't provided as keys to the constructor (unless you use init_arg => undef
to prevent them from being set in the constructor).
If your config is an attribute of its own, with a builder that reads the config file, then you have an ordering problem between config
and teachers_file
and students_file
. You can resolve this by making teachers_file
and students_file
lazy attributes, which ensures that they won't try to be constructed before the config attribute. However, you may want to make sure that the "foo is not a readable file" error is thrown as early as possible during construction, instead of the first time the attribute is used. You can work around that by adding
sub BUILD {
my $self = shift;
$self->teachers_file;
$self->students_file;
}
which ensures that those attributes are read once (and constructed) before the constructor returns.
精彩评论