Mooish::AttributeBuilder - build Mooish attribute definitions with less boilerplate
use Moo; # or Moose or Mouse or ... use Mooish::AttributeBuilder; # this attribute is required in the constructor has param 'param_name'; has param 'param_name' => ( ... ); # this attribute is optional in the constructor has option 'option_name'; has option 'option_name' => ( ... ); # this attribute is not available in the constructor has field 'field_name'; has field 'field_name' => ( ... ); # this extends parent attribute, much like: has '+name_to_extend' has extended 'name_to_extend' => ( ... );
This module implements shortcuts and helpers for has keyword in Moose family of modules.
has
The shortcuts provided are similar to those in MooseX::Extended or MooX::Keyword::Field, but they don't depend on specific OO system. Instead, those shortcuts are just modifying option lists which are then passed to has. This way you can use the module with any OO system which supports the Moose set of has parameters.
All functions are exported by default.
has field $field_name => %more_options;
This function produces a property that cannot be passed to the constructor:
has $field_name => ( is => 'ro', init_arg => undef, %more_options );
has param $param_name => %more_options;
This function produces a property that is required in the constructor:
has $param_name => ( is => 'ro', required => 1, %more_options );
has option $option_name => %more_options;
This function produces a property that is optional in the constructor and has a predicate:
has $option_name => ( is => 'ro', required => 0, predicate => "has_${option_name}", %more_options );
has extended $name_to_extend => %more_options;
This function does not introduce any extra hash keys, but adds a plus sign before the name:
has "+${name_to_extend}" => ( %more_options );
The %more_options hash can contain some shortcuts that will be expanded by "option", "param", "field" or "extended" functions.
%more_options
The following values:
1 -public -hidden
... can be passed to the following options, producing standard method names with given prefixes:
reader: get_ writer: set_ predicate: has_ clearer: clear_ builder: _build_ trigger: _trigger_
The naming rules are as follows:
Properties starting with an underscore produce hidden methods when passed 1 (starting with underscore as well)
1
has field '_name' => ( reader => 1 ); # ... becomes: has '_name' => ( ... reader => '_get_name' );
Properties not starting with an underscore produce public methods when passed 1 (not starting with underscore)
has field 'name' => ( writer => 1 ); # ... becomes: has 'name' => ( ... writer => 'set_name' );
Visibility can be forced by passing -public or -hidden instead of 1
-public
-hidden
has field '_name' => ( predicate => -public ); # ... becomes: has '_name' => ( ... predicate => 'has_name' ); has field 'name' => ( predicate => -hidden ); # ... becomes: has 'name' => ( ... predicate => '_has_name' );
builder and trigger are hidden by default. The only way to have them not start with an underscore (other than passing the name explicitly) is to pass -public.
builder
trigger
These two options also don't change the name based on the leading underscore in property's name. Builders for property and _property will by default both be _build_property.
property
_property
_build_property
lazy => sub { return 'default value' }
... will be expanded to:
lazy => 1, default => sub { return 'default value' }
Note: this only works for anonymous subroutines. Will not be expanded if explicit default / builder was passed (but does not take superclass default / builder into account).
lazy => 'builder_name'
lazy => 1, builder => 'builder_name'
Note: passing 1 will work as described in "method name shortcuts". Will not be expanded if explicit default / builder was passed (but does not take superclass default / builder into account).
coerce => Types::Standard::Int
isa => Types::Standard::Int, coerce => 1
As long as it is a blessed reference (object).
Having a builder or a default will automatically remove required from the option list.
default
required
# will no longer be required in the constructor has param 'optional' => ( default => undef, );
init_arg can use the same shortcuts as described in "method name shortcuts".
init_arg
This can be useful to turn _name into name in the constructor with the help of -public:
_name
name
# no underscore in the constructor has param '_name' => ( init_arg => -public, );
In addition to shortcuts described in "method name shortcuts", trigger can now be passed both as a anon sub (like default) or as a package sub name (like builder).
In case you want to fall back to default behavior of some has parameters, you can prepend their names with a hyphen:
# 'builder' will be expanded, but 'writer' won't has field 'auto' => ( builder => 1, -writer => 1, );
It is possible to introduce custom shortcuts by calling add_shortcut:
add_shortcut
use Mooish::AttributeBuilder; use Data::Dumper; Mooish::AttributeBuilder::add_shortcut(sub { my ($name, %args) = @_; print Dumper(\%args); return %args; });
Each new option filter must be an anonymous subroutine that accepts ($name, %args) and returns new value for %args. $name will contain full name of the attribute (which can be an array reference), while %args are attribute options plus a "_type" key, which is the name of the helper, e.g. "param".
($name, %args)
%args
$name
"_type"
"param"
Custom shortcuts are called before built in shortcuts described in "SHORTCUTS", in order of declaration. Make sure not to call add_shortcut repeatedly with the same sub, as the module will not run any checks to prevent duplication.
Example, making fields rw by default:
rw
Mooish::AttributeBuilder::add_shortcut(sub { my ($name, %args) = @_; if ($args{_type} eq 'field') { $args{is} = 'rw'; } return %args; });
If you want to use Mooish::AttributeBuilder in your module, these custom filters are undesirable. You want to be sure your module works regardless of environment. In CPAN modules the module should be imported with the -standard flag, which will disable all custom behavior.
-standard
use Mooish::AttributeBuilder -standard;
This flag was added in Mooish::AttributeBuilder version 1.001.
1.001
The module lets you write for example:
has field ['f1', 'f2'] => %params; has extended ['f3', 'f4'] => %params;
These constructions work, but since we operate on a single has here, %params can't contain shortcuts which produces method names - that would lead to multiple fields using same methods. The module will die with a helpful error message if it encounters something that it can't handle properly.
%params
If you encounter this problem, you might want to "use parameter value without expanding" to fall back to regular shortcut modules (like MooseX::AttributeShortcuts). This module will not automatically change its behavior to do so, so it does not surprise you.
Since the module does not depend on specific OO implementation, the only common is => options are ro and rw (as in base Moose). The author considers rw to be a bad idea most of the time. Having one method for reading and writing can lead to bugs that are hard to spot.
is =>
ro
Other than that:
writer => -hidden shortcut does more or less what rwp does.
writer => -hidden
rwp
lazy => 1 shortcut does more or less what lazy does.
lazy => 1
lazy
The module implements many of the shortcuts from MooseX::AttributeShortcuts, but does not aim to have 100% compatibility. Some details in overlapping functionality may differ.
Bartosz Jarzyna <bbrtj.pro@gmail.com>
Copyright (C) 2022 by Bartosz Jarzyna
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
To install Mooish::AttributeBuilder, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Mooish::AttributeBuilder
CPAN shell
perl -MCPAN -e shell install Mooish::AttributeBuilder
For more information on module installation, please visit the detailed CPAN module installation guide.