Mite::Manual::Attributes - options for defining attributes with Mite
has myattr => ( alias => [ 'my_attr' ], is => 'bare', # or ro/rw/rwp/lazy init_arg => 'myattr', required => true, reader => 'get_myattr', writer => 'set_myattr', accessor => 'access_myattr', clearer => 'clear_myattr', predicate => 'has_myattr', lvalue => 'myattr', local_writer => 'locally_set_myattr', # default => sub { shift->_build_myattr }, builder => '_build_myattr', lazy => false, isa => 'Object', coerce => false, clone => false, locked => false, handles => { quux => 'quuux' }, handles_via => [ 'Blessed' ], trigger => '_trigger_myattr', );
Shortcut for a lazy builder:
has myattr => sub { ... };
Shortcut for a simple default:
has myattr => "some value";
Like has in Moose, this declares an attribute.
has
Multiple attributes can be defined using an arrayref.
# Defines get_foo, get_bar, set_foo, and set_bar. # has [ 'foo', 'bar' ] => ( isa => 'Str', reader => 1, writer => 1, );
Like in Moose, you can use a plus sign to modify an attribute definition from a role or parent class:
has '+foo' => ( default => sub { 'new default' }, );
When modifying an attribute, you cannot use the is option.
is
Mite objects are always blessed hashrefs, and the name of the attribute is the hash key used to store the attribute.
It is the maintainer of Mite's opinion that it is acceptable for an object method to directly access its own attributes this way, but not attributes defined in roles, parent classes, etc. Bypassing accessors will cause type checks, lazy defaults, triggers, etc to be ignored, so should be done with caution.
The following options are supported. (Expected types for the value of each option are also provided. A MethodName is any valid Perl sub name; a MethodNameTemplate may also contain "%s" as a placeholder; One means the literal string "1". Other type constraints are self-explanatory.)
These are all just shortcuts for defining other options.
Supported values for is include "ro", "rw", and "bare" like Moose, but also "rwp" and "lazy" like Moo. Lastly "locked" is an alias for "ro", but also sets the locked option to true.
locked
The default is is => 'bare'.
is => 'bare'
reader
The name of the attribute reader method to generate. If set to "1", will generate a reader called "get_foo" if your attribute is called "foo" and "_get__foo" if your attribute is called "_foo".
If your attribute is defined as is => "ro", is => "rwp", is => "lazy", or is => "locked", then reader defaults to $name.
is => "ro"
is => "rwp"
is => "lazy"
is => "locked"
$name
If your reader contains "%s" this will be replaced by the name of the attribute. This allows:
# readers called "fetch_foo" and "fetch_bar" has [ 'foo', 'bar' ] => ( required => true, reader => 'fetch_%s', );
writer
The name of the attribute writer method to generate. If set to "1", will generate a writer called "set_foo" if your attribute is called "foo" and "_set__foo" if your attribute is called "_foo".
If your attribute is defined as is => "rwp", then writer defaults to "_set_$name".
"_set_$name"
If your writer contains "%s" this will be replaced by the name of the attribute.
Mite provides a similar feature to MooseX::Attribute::Chained, so writer methods return $self, allowing them to be chained:
$self
$object->set_bar( 42 )->set_baz( 99 );
accessor
The name of the dual-purpose attribute reader/writer method to generate. If set to "1", will generate a reader called "foo" if your attribute is called "foo" and "_foo" if your attribute is called "_foo".
If your attribute is defined as is => "rw", then accessor defaults to $name.
is => "rw"
If your accessor contains "%s" this will be replaced by the name of the attribute.
Mite provides a similar feature to MooseX::Attribute::Chained, so accessor methods called as writers return $self, allowing them to be chained:
$object->bar( 42 )->baz( 99 );
clearer
The name of the attribute clearer method to generate. If set to "1", will generate a clearer called "clear_foo" if your attribute is called "foo" and "_clear__foo" if your attribute is called "_foo".
If your clearer contains "%s" this will be replaced by the name of the attribute.
Mite provides a similar feature to MooseX::Attribute::Chained, so clearer methods return $self, allowing them to be chained:
$object->clear_foo->clear_bar->clear_baz;
predicate
The name of the attribute predicate method to generate. If set to "1", will generate a predicate called "has_foo" if your attribute is called "foo" and "_has__foo" if your attribute is called "_foo".
If your predicate contains "%s" this will be replaced by the name of the attribute.
lvalue
The name of the dual-purpose lvalue reader/writer method to generate. If set to "1", will generate a reader called "foo" if your attribute is called "foo" and "_foo" if your attribute is called "_foo".
lvalue accessors are used like this:
my $object = MyClass->new( myattr => 99 ); say $object->myattr; # ==> 99 $object->myattr = 66; # set new value say $object->myattr; # ==> 66
An attribute cannot have an lvalue accessor if it has a lazy builder/default, uses a type contraint or coercions, has a trigger, or uses weak_ref.
This is roughly (but not exactly) the same functionality as MooseX::LvalueAttribute.
local_writer
The name of the dynamically scoped writer method to generate. These work like this:
my $object = Your::Project::SomeClass->new( foo => 99 ); say $object->foo; # ==> 99 do { my $guard = $object->locally_set_foo( 66 ); say $object->foo; # ==> 66 }; say $object->foo; # ==> 99
When the $guard goes out of scope, the old value will be restored. The $guard object also has three methods: restore to restore the old value immediately, dismiss to dismiss the old value and keep the new value, and peek to peek at the old value.
$guard
restore
dismiss
peek
If the local writer is called with no parameter, it acts as a local clearer.
If set to "1", will generate a local writer called "locally_set_foo" if your attribute is called "foo" and "_locally_set__foo" if your attribute is called "_foo".
If your local writer contains "%s" this will be replaced by the name of the attribute.
This is vaguely inspired by MooseX::LocalAttribute.
skip_argc_check
Mite includes sanity checks on the number of arguments passed to accessors. For example, if you call a reader and pass it a value as if it were a writer, it will die with a message explaining the problem.
You can set skip_argc_check to true to skip these checks for an attribute's accessors, making it run a little faster. If Class::XSAccessor is installed and being used, these checks will still be done in XS mode, so skip_argc_check shouldn't be used as a way to allow the wrong number of arguments to be passed to a function, just as an optimization.
handles
Delegated methods. Currying and native traits are not supported.
If your handles hashref keys contain "%s", they will be replaced by the name of the attribute.
# $this->user_agent_get is a shortcut for $this->user_agent->get # has user_agent => ( required => true, isa => 'Object', handles => { '%s_get' => 'get', '%s_post' => 'post', }, );
If the attribute's type constraint is an enumeration, then the shortcuts handles => 1 and handles => 2 are also supported. These are inspired by MooseX::Enumeration and MooX::Enumeration.
handles => 1
handles => 2
In this example, Mite creates methods is_alive and is_dead for you:
is_alive
is_dead
has status => ( enum => [ 'alive', 'dead' ], handles => 1, default => 'alive', writer => '_set_status', ); sub kill { my $self = shift; croak "Already dead!" if $self->is_dead; $self->_set_status( 'dead' ); }
In this example, Mite creates size_is_small, size_is_medium, and size_is_large for you.
size_is_small
size_is_medium
size_is_large
has size => ( is => 'rw', isa => 'Enum[ "small", "medium", "large" ]', handles => 2, );
Note that if handles had been 1, then the methods would have just been called is_small, is_medium, and is_large, without the size_ prefix at the start.
is_small
is_medium
is_large
size_
handles_via
If handles_via is set, then Mite will use Sub::HandlesVia for dealing with the handles option instead of trying to deal with it internally. This allows a rich set of delegations to native Perl types like arrayrefs and hashrefs.
has monkeys => ( is => 'bare', isa => 'ArrayRef[Object]', handles_via => 'Array', handles => { '%s' => 'all', monkey_count => 'count', add_monkey => 'push...', find_monkeys => 'grep', clear_monkeys => 'clear...', }, ); ... $zoo->clear_monkeys(); $zoo->add_monkey( $bobo ); $zoo->add_monkey( $momo ); if ( $zoo->monkey_count == 0 ) { say "No monkeys!"; } for my $monkey ( $zoo->monkeys ) { say $monkey->name; }
Most Sub::HandlesVia features should be supported.
init_arg
The parameter expected to be passed to the constructor to initialize this attribute. May be undef if the attribute should not be intitialized in the constructor.
Defaults to the attribute's name.
If your init_arg contains "%s" this will be replaced by the name of the attribute.
required
Indicates whether the attribute is required in the constructor. If the attribute has a non-lazy default, this is ignored.
alias
A list of aliases for the attibutes. If the attribute has an init_arg (including a default one), this provides alternative initialization arguments. If the attribute is => "rw", then these aliases are aliases for the accessor; otherwise they are aliases for the reader.
The strings can contain "%s" which will be replaced by the attribute name, allowing this to work:
has [ 'foo', 'bar' ] => ( is => 'ro', alias => [ 'get_%s' ], );
If you try to create aliases but don't have a reader or accessor, then as a last resort the alias will be an alias for the writer.
# foo can be set using `set_foo` or `whatever` # has foo => ( is => 'bare', writer => 1, alias => 'whatever', # Mite will implicitly do Str -> ArrayRef here );
Aliases are not natively supported by Moose, but this feature is analagous to MooseX::Aliases.
isa
A string type name from Types::Standard, Types::Common::String, or Types::Common::Numeric, or a blessed Type::Tiny object. Alternatively, any reference which to_TypeTiny from Types::TypeTiny is able to coerce to a blessed Type::Tiny object, or any blessed object that provides a to_TypeTiny method which returns a Type::Tiny object. If using a blessed object, you'll be introducing a dependency for your project on whatever type constraint library you're using, so prefer string type contraint names.
to_TypeTiny
Any string supported by Type::Utils dwim_type is supported, so things like "Int | Enum['small', 'medium', 'large']" should work!
dwim_type
"Int | Enum['small', 'medium', 'large']"
If you need custom types, you can add something like this to your .mite/config:
types: Your::Project::Types
The module Your::Project::Types would be a type library constructed with Type::Library. It should just contain type constraints and coercions which can be inlined, and none of your classes should load it directly (just rely on Mite to load it). This way you can use custom types in your project and your project will not have a dependency on Type::Library.
Your::Project::Types
Type::Library::Compiler is an alternative way to create a zero-dependency type library which Mite is able to use.
does
Same as isa, but if the type name is unrecognized, assumes it was a role name instead of assuming it was a class name.
enum
Shortcut for isa => 'Enum["foo","bar","baz"]'.
isa => 'Enum["foo","bar","baz"]'
This feature is inspired by MooseX::Enumeration and MooX::Enumeration.
coerce
Indicates that the attribute should attempt to coerce values to fit the type constraint.
trigger
If set to a string, is the name of a method to call whenever a new attribute value is set. This is not called when an attribute is defaulted. (However, see the default_does_trigger option.) If set to "1", will assume a trigger called "_trigger_foo" if your attribute is called "foo" and "_trigger__foo" if your attribute is called "_foo".
default_does_trigger
If set to a coderef, acts like it was set to "1" but installs the coderef into your class with that name.
If your trigger method name contains "%s" this will be replaced by the name of the attribute.
weak_ref
Indicates that the attribute should weaken its reference to the attribute value.
If an attribute is locked and its value is set to an unblessed arrayref or hashref, then the array or hash will be marked as read-only. This means that if you've defined an attribute like this:
has numbers => ( is => ro, isa => 'ArrayRef', locked => true, default => [], );
People will not be able to do push( @{ $object->numbers }, 1 ), and it will throw an exception!
push( @{ $object->numbers }, 1 )
To allow people to push to the array:
has numbers => ( is => ro, isa => 'ArrayRef', locked => true, default => [], handles_via => 'Array', handles => { add_number => 'push', remove_number => 'pop' }, );
Then they can use $object->add_number( 1 ).
$object->add_number( 1 )
Defaults to false, unless is => "locked".
clone
Stolen from MooseX::Extended. Set to "1" to make a deep clone of the attribute value using Storable whenever the attribute is read or written. If set to a method name or coderef, then the method will be called as $self->$method( $attrname, $value ) and is expected to return a clone of the value.
$self->$method( $attrname, $value )
has start_date => ( is => ro, isa => 'InstanceOf["DateTime"]', required => true, clone => sub { my ( $self, $attrname, $value ) = @_; return $value->clone; }, );
This option can be fine-tuned by setting the clone_on_read and clone_on_write boolean options. By default, attributes which have a clone method set will clone both incoming and outgoing references.
clone_on_read
clone_on_write
has start_date => ( is => ro, isa => 'InstanceOf["DateTime"]', required => true, clone => sub { my ( $self, $attrname, $value ) = @_; return $value->clone; }, clone_on_write => true, clone_on_read => false, );
default
A default value for the attribute, or a coderef called as a method to generate that default value.
Unlike Moose, you can alternatively include an inline string of Perl code as a ScalarRef:
has list => ( is => 'ro', isa => 'ArrayRef', default => \ '[]', );
This has performance benefits over using a coderef as it avoids the overhead of a sub call.
An empty arrayref or empty hashref is also allowed as a default.
builder
If set to a string, is the name of a method to call to build the default attribute value. If set to "1", will assume a builder called "_build_foo" if your attribute is called "foo" and "_build__foo" if your attribute is called "_foo".
If you used is => "lazy", this will default to "1".
If your builder method name contains "%s" this will be replaced by the name of the attribute.
lazy
Indicates that the default should be set lazily. Defaults to false unless you used is => "lazy".
An eager (non-lazy) default or builder is applied by the constructor when the object is constructed. A lazy default or builder is applied by the reader/accessor if and when the attribute is accessed.
default_is_trusted
Defaults to false (which is how Moose and Moo work), but if set to true, Mite will skip type checks and coercions when the attribute is set by the default or builder. If you trust that the default is always going to be a valid value, then it may make sense to only do type checks and coercions when a value is passed in by your caller. This may make your accessors and constructor a little faster.
Defaults to false (which is how Moose and Moo work), but if set to true, Mite will also call your trigger if the attribute's default is used. Normally triggers are only called when an attribute is set explicitly.
documentation
This option is ignored, but you can set it to a documentation string for your attribute.
has name => ( is => 'rwp', isa => 'Str', documentation => 'First name and surname', );
is => 'wo'
There are use cases for write-only attributes. For example:
package Your::Project::ApiClient; use Your::Project::Mite; has user_agent => ( is => 'wo', isa => 'Object', handles => [ 'get', 'post' ], builder => sub { require HTTP::Tiny; HTTP::Tiny->new }, ); ... $client->user_agent( HTTP::Tiny::WithLogging->new ); $client->post( ... ); $client->user_agent(); # dies, because it's a writer
However, Mite doesn't support is => 'wo'. (Neither do Moose, Mouse, or Moo!) So how can this be accomplished?
This will provide a writer method called user_agent:
user_agent
has user_agent => ( writer => '%s', isa => 'Object', handles => [ 'get', 'post' ], builder => sub { require HTTP::Tiny; HTTP::Tiny->new }, );
Alternatively, this will provide a writer method called set_user_agent:
set_user_agent
has user_agent => ( writer => 1, isa => 'Object', handles => [ 'get', 'post' ], builder => sub { require HTTP::Tiny; HTTP::Tiny->new }, );
Please report any bugs to https://github.com/tobyink/p5-mite/issues.
Michael G Schwern <mschwern@cpan.org>.
Toby Inkster <tobyink@cpan.org>.
This software is copyright (c) 2011-2014 by Michael G Schwern.
This software is copyright (c) 2022 by Toby Inkster.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.
THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
To install Mite, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Mite
CPAN shell
perl -MCPAN -e shell install Mite
For more information on module installation, please visit the detailed CPAN module installation guide.