Venus::Role::Coercible

Coercible Role

Coercible Role for Perl 5

method: coerce_args method: coerce_attr method: coerce_into method: coerce_onto method: coercers method: coercion

package Person;

use Venus::Class;

with 'Venus::Role::Coercible';

attr 'name';
attr 'father';
attr 'mother';
attr 'siblings';

sub coercers {
  {
    father => 'Person',
    mother => 'Person',
    name => 'Venus/String',
    siblings => 'Person',
  }
}

sub coerce_name {
  my ($self, $code, @args) = @_;

  return $self->$code(@args);
}

sub coerce_siblings {
  my ($self, $code, $class, $value) = @_;

  return [map $self->$code($class, $_), @$value];
}

package main;

my $person = Person->new(
  name => 'me',
  father => {name => 'father'},
  mother => {name => 'mother'},
  siblings => [{name => 'brother'}, {name => 'sister'}],
);

# $person
# bless({...}, 'Person')

# $person->name
# bless({...}, 'Venus::String')

# $person->father
# bless({...}, 'Person')

# $person->mother
# bless({...}, 'Person')

# $person->siblings
# [bless({...}, 'Person'), bless({...}, 'Person'), ...]

This package modifies the consuming package and provides methods for hooking into object construction and coercing arguments into objects and values.

The coerce_args method replaces values in the data provided with objects corresponding to the specification provided. The specification should contains key/value pairs where the keys map to class attributes (or input parameters) and the values are Venus::Space compatible package names.

coerce_args(hashref $data, hashref $spec) (hashref)

{ since => '0.07', }

=example-1 coerce_args

package main;

my $person = Person->new;

my $data = $person->coerce_args(
  {
    father => { name => 'father' }
  },
  {
    father => 'Person',
  },
);

# {
#   father   => bless({...}, 'Person'),
# }

The coerce_attr method is a surrogate accessor and gets and/or sets an instance attribute based on the coercion rules, returning the coerced value.

coerce_attr(string $name, any $value) (any)

{ since => '1.23', }

=example-1 coerce_attr

# given: synopsis

package main;

$person = Person->new(
  name => 'me',
);

my $coerce_name = $person->coerce_attr('name');

# bless({value => "me"}, "Venus::String")

The coerce_into method attempts to coerce the value provided into an object of the specified class. If the value is already an object of that class, it is returned as-is. Otherwise, the method tries to find a suitable coercion method to convert the value based on its type. If no specific coercion method is found, it defaults to constructing a new instance of the target class using the provided value.

This method supports dynamic coercion by dispatching to a method on the invocant (if present) named in the format coerce_into_${class}_from_${type} or coerce_into_${class}, where $class is the name of the desired object class, and $type is the data type of the value provided. If neither method is found, it defaults to checking if the value is already of the target type or creating a new instance of the target class.

The class name used in the method name will be formatted as a lowercase string having underscores in place of any double-semi-colons.

For example: Example::Package will be example_package making the method name coerce_into_example_package.

The following are the possible values for data types that can be used in the method name:

+=over 4

+=item * arrayref

+=item * boolean

+=item * coderef

+=item * float

+=item * hashref

+=item * number

+=item * object

+=item * regexp

+=item * scalarref

+=item * string

+=item * undef

+=back

For example: Coercing a string into the Example::Package would warrant the method name coerce_into_example_package_from_string.

coerce_into(string $class, any $value) (object)

{ since => '0.07', }

=example-1 coerce_into

package main;

my $person = Person->new;

my $friend = $person->coerce_into('Person', {
  name => 'friend',
});

# bless({...}, 'Person')

The coerce_onto method attempts to build and assign an object based on the class name and value provided, as the value corresponding to the name specified, in the data provided. If the $value is omitted, the value corresponding to the name in the $data will be used.

The coerce_onto method attempts to coerce the value provided into an object of the specified class, and add it as an item in the data structure provided. If the value is already an object of that class, it is returned as-is. Otherwise, the method tries to find a suitable coercion method to convert the value based on its type. If no specific coercion method is found, it defaults to constructing a new instance of the target class using the provided value.

This method supports dynamic coercion by dispatching to a method on the invocant (if present) named in the format coerce_onto_${class}_from_${type} or coerce_onto_${class} or coerce_${class}, where $class is the name of the desired object class, and $type is the data type of the value provided. If neither method is found, it defaults to checking if the value is already of the target type or creating a new instance of the target class.

The class name used in the method name will be formatted as a lowercase string having underscores in place of any double-semi-colons.

For example: Example::Package will be example_package making the method name coerce_into_example_package.

The following are the possible values for data types that can be used in the method name:

+=over 4

+=item * arrayref

+=item * boolean

+=item * coderef

+=item * float

+=item * hashref

+=item * number

+=item * object

+=item * regexp

+=item * scalarref

+=item * string

+=item * undef

+=back

For example: Coercing a string into the Example::Package would warrant the method name coerce_onto_example_package_from_string.

coerce_onto(hashref $data, string $name, string $class, any $value) (object)

{ since => '0.07', }

=example-1 coerce_onto

package main;

my $person = Person->new;

my $data = { friend => { name => 'friend' } };

my $friend = $person->coerce_onto($data, 'friend', 'Person');

# bless({...}, 'Person'),

# $data was updated
#
# {
#   friend => bless({...}, 'Person'),
# }

The coercers method, if defined, is called during object construction, or by the "coercion" method, and returns key/value pairs where the keys map to class attributes (or input parameters) and the values are Venus::Space compatible package names.

coercers() (hashref)

{ since => '0.02', }

=example-1 coercers

package main;

my $person = Person->new(
  name => 'me',
);

my $coercers = $person->coercers;

# {
#   father   => "Person",
#   mother   => "Person",
#   name     => "Venus/String",
#   siblings => "Person",
# }

The coercion method is called automatically during object construction but can be called manually as well, and is passed a hashref to coerce and return.

coercion(hashref $data) (hashref)

{ since => '0.02', }

=example-1 coercion

package main;

my $person = Person->new;

my $coercion = $person->coercion({
  name => 'me',
});

# $coercion
# {...}

# $coercion->{name}
# bless({...}, 'Venus::String')

# $coercion->{father}
# undef

# $coercion->{mother}
# undef

# $coercion->{siblings}
# undef

t/Venus.t: present: authors t/Venus.t: present: license

32 POD Errors

The following errors were encountered while parsing the POD:

Around line 14:

Unknown directive: =name

Around line 22:

Unknown directive: =tagline

Around line 30:

Unknown directive: =abstract

Around line 38:

Unknown directive: =includes

Around line 51:

Unknown directive: =synopsis

Around line 144:

Unknown directive: =description

Around line 153:

Unknown directive: =method

Around line 160:

Unknown directive: =signature

Around line 164:

Unknown directive: =metadata

Around line 201:

Unknown directive: =method

Around line 206:

Unknown directive: =signature

Around line 210:

Unknown directive: =metadata

Around line 255:

=cut found outside a pod block. Skipping to next block.

Around line 266:

Unknown directive: =method

Around line 320:

Unknown directive: =signature

Around line 324:

Unknown directive: =metadata

Around line 378:

=cut found outside a pod block. Skipping to next block.

Around line 413:

=cut found outside a pod block. Skipping to next block.

Around line 424:

Unknown directive: =method

Around line 483:

Unknown directive: =signature

Around line 487:

Unknown directive: =metadata

Around line 574:

=cut found outside a pod block. Skipping to next block.

Around line 632:

=cut found outside a pod block. Skipping to next block.

Around line 684:

=cut found outside a pod block. Skipping to next block.

Around line 696:

Unknown directive: =method

Around line 703:

Unknown directive: =signature

Around line 707:

Unknown directive: =metadata

Around line 745:

Unknown directive: =method

Around line 750:

Unknown directive: =signature

Around line 754:

Unknown directive: =metadata

Around line 836:

=cut found outside a pod block. Skipping to next block.

Around line 868:

Unknown directive: =partials