The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Object::Depot - Decouple object instantiation from usage.

SYNOPSIS

    use Object::Depot;

    my $depot = Object::Depot->new(
        class => 'CHI',
        # CHI->new returns a CHI::Driver object.
        type => InstanceOf[ 'CHI::Driver' ],
    );

    $depot->add_key(
        sessions => {
            driver => 'Memory',
            global => 1,
        },
    );

    $depot->store( ip2geo => CHI->new(...) );

    my $sessions = $depot->fetch('sessions');
    my $ip2geo = $depot->fetch('ip2geo');

DESCRIPTION

Object depots encapsulate object construction so that users of objects do not need to know how to create the objects in order to use them.

The primary use case for this library is for storing the connection logic to external services and making these connections globally available to all application logic. See Object::Depot::Role for turning your depot object into a global singleton.

ARGUMENTS

class

    class => 'CHI',

The class which objects in this depot are expected to be. This argument defaults the "constructor" and "type" arguments.

Does not have a default.

Leaving this argument unset causes "fetch" to fail on keys that were not first populated with "store" as the "constructor" subroutine will just return undef.

constructor

    constuctor => sub{
        my ($args) = @_;
        return __PACKAGE__->depot->class->new( $args );
    },

Set this to a code ref to control how objects get constructed.

When declaring a custom constructor be careful not to create memory leaks via circular references.

"create" validates the objects produced by this constructor and will throw an exception if they do not match "type".

The default code ref is similar to the above example if "class" is set. If it is not set then the default code ref will return undef.

type

    type => InstanceOf[ 'CHI::Driver' ],

Set this to a Type::Tiny type to control how objects in the depot are validated when they are stored.

Defaults to InstanceOf "class", if set. If the class is not set then this defaults to Object (both are from Types::Standard).

injection_type

    injection_type => Object,

By default objects that are injected (see "inject") are validated against "type". Set this to a type that injections validate against if it needs to be different (such as to support mock objects).

per_process

    per_process => 1,

Turn this on to store objects per-process; meaning, if the TID (thread ID) or PID (process ID) change then this depot will act as if no objects have been stored. Generally you will not want to turn this on. On occasion, though, some objects are not thread or forking safe and it is necessary.

Defaults off.

disable_store

    disable_store => 1,

When on this causes "store" to silently not store, causing all "fetch" calls for non-injected keys to return a new object.

Defaults off.

strict_keys

    strict_keys => 1,

Turn this on to require that all keys used must first be declared via "add_key" before they can be stored in the depot.

Defaults to off, meaning keys may be used without having to pre-declare them.

default_key

    default_key => 'generic',

If no key is passed to key-accepting methods like "fetch" then they will use this default key if available.

Defaults to no default key.

key_argument

    key_argument => 'connection_key',

When set, this causes "arguments" to include an extra argument to be passed to the class during object construction. The argument's key will be whatever you set this to and the value will be the key used to fetch the object.

You will still need to write the code in your class to capture the argument, such as:

    has connection_key => ( is=>'ro' );

Defaults to no key argument.

default_arguments

    default_arguments => {
        arg => 'value',
        ...
    },

When set, these arguments will be included in calls to "arguments".

Defaults to an empty hash ref.

export_name

    export_name => 'myapp_cache',

Set the name of a function that Object::Depot::Role will export to importers of your depot package.

Has no default. If this is not set, then nothing will be exported.

always_export

    always_export => 1,

Turning this on causes Object::Depot::Role to always export the "export_name", rather than only when listed in the import arguments. This is synonymous with the difference between Exporter's @EXPORT_OK and @EXPORT.

METHODS

active_objects

    my @objects = $depot->active_objects();

Return an array containing all active objects the depot created via calls to $depot->create().

If per_process is set, returns only active objects created by the current process/thread.

fetch

    my $object = $depot->fetch( $key );

store

    $depot->store( $key => $object );

remove

    $depot->remove( $key );

create

    my $object = $depot->create( $key, %extra_args );

Gathers arguments from "arguments" and then calls "constructor" on them, returning a new object. Extra arguments may be passed and they will take precedence.

arguments

    my $args = $depot->arguments( $key, %extra_args );

This method returns an arguments hash ref that would be used to instantiate a new "class" object. You could, for example, use this to produce a base-line set of arguments, then sprinkle in some more, and make yourself a special mock object to be injected.

declared_keys

    my $keys = $depot->declared_keys();
    foreach my $key (@$keys) { ... }

Returns an array ref containing all the keys declared with "add_key".

inject

    $depot->inject( $key, $object );

Takes an object of your making and forces "fetch" to return the injected object. This is useful for injecting mock objects in tests.

The injected object must validate against "type".

inject_with_guard

    my $guard = $depot->inject_with_guard( $key => $object );

This is just like "inject" except it returns a Guard object which, when it leaves scope and is destroyed, will automatically call "clear_injection".

clear_injection

    my $object = $depot->clear_injection( $key );

Removes and returns the injected object, restoring the original behavior of "fetch".

injection

    my $object = $depot->injection( $key );

Returns the injected object, or undef if none has been injected.

has_injection

    if ($depot->has_injection( $key )) { ... }

Returns true if an injection is in place for the specified key.

add_key

    $depot->add_key( $key, %arguments );

Declares a new key and, optionally, the arguments used to construct the "class" object.

Arguments are optional, but if present they will be saved and used by "fetch" when calling new() (via "arguments") on "class".

alias_key

    $depot->alias_key( $alias_key => $real_key );

Adds a key that is an alias to another key.

SUPPORT

Please submit bugs and feature requests to the Object-Depot GitHub issue tracker:

https://github.com/bluefeet/Object-Depot/issues

ACKNOWLEDGEMENTS

Thanks to ZipRecruiter for encouraging their employees to contribute back to the open source ecosystem. Without their dedication to quality software development this distribution would not exist.

AUTHORS

    Aran Clary Deltac <bluefeet@gmail.com>

LICENSE

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.