The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Catalyst::Plugin::MapComponentDependencies - Allow components to depend on other components

SYNOPSIS

    package MyApp;

    use Moose;
    use Catalyst;

    with 'Catalyst::Plugin::MapComponentDependencies';

    MyApp->map_dependencies(
      'Model::Foo' => {
        bar => 'Model::Bar',
        baz => sub {
          my ($app_or_ctx, $component_name) = @_;
          return ...;
        },
      },
    );

    MyApp->config(
      'Model::Foo' => { another_param => 'value' }
    )

    MyApp->setup;

During setup when 'Model::Foo' is created it will get all three key / value pairs send to ->new.

NOTE: You need to compose this plugin via the Moose 'with' subroutine if you want to get the handy class methods 'map_dependencies' and 'map_dependency'. If you prefer you may setup you dependencies via configuration:

    package MyApp;

    use Catalyst 'MapComponentDependencies';

    MyApp->config(
      'Model::Foo' => { another_param => 'value' },
      'Plugin::MapComponentDependencies' => {
        map_dependencies => {
          'Model::Foo' => {
            bar => 'Model::Bar',
            baz => sub {
              my ($app_or_ctx, $component_name, $from_config_args) = @_;
              return ...;
            },
          },
        },
      },
    );

    MyApp->setup;

Alternatively you may choose a 'shorthand' version of the configuration based approach:

    package MyApp;

    use Catalyst 'MapComponentDependencies';

    MyApp->config(
      'Model::Foo' => { another_param => 'value' },
      'Plugin::MapComponentDependencies' => {
        'Model::Foo' => {
          bar => 'Model::Bar',
          baz => sub {
            my ($app_or_ctx, $component_name, $from_config_args) = @_;
            return ...;
          },
        },
      },
    );

    MyApp->setup;

You may prefer this if your dependencies will map differently based on environment and configuration settings.

Lastly you may use the helper utilities to create a single merged configuration for your dependencies:

    package MyApp;

    use Moose;
    use Catalyst 'MapComponentDependencies;
    use Catalyst::Plugin::MapComponentDependencies::Utils ':All';

    MyApp->config(
      'Model::Bar' => { key => 'value' },
      'Model::Foo' => {
        bar => FromModel 'Bar',
        baz => FromCode {
          my ($app_or_ctx, $component_name) = @_;
          return ...;
        },
        another_param => 'value',
      },
    );

    MyApp->setup;

See Catalyst::Plugin::MapComponentDependencies::Utils for more.

DESCRIPTION

Sometimes you would like a Catalyst component to depend on the value of an existing component. Since components are resolved during application setup (or at request time, in the cause of a component that does ACCEPT_CONTEXT) you cannot specify this dependency mapping in the 'normal' Catalyst configuration hash.

This plugin, which requires a recent Catalyst of version 5.90090+, allows you to define components which depend on each other. You can also set the value of an initial argument to the value of a coderef, for added dynamic flexibility.

You may define dependencies in one of two ways. The first way is to use a key/value pair to map a configuation key attribute to the value of an existing Catalyst model. When the depending model is called, we get the value of that model in the same way as if we called '$c->model($name)'. You can by the way use any type of Catalys component as a value (models, views and even controllers).

The second way is to use a coderef, which is expected to return a value suitable for the depending model. This gives you a little more flexibility for crafting very custom types of dependencies. If you use a coderef you will get three values, the application (or context depending on if the depending model does ACCEPT_CONTEXT), the component name and a reference to any static configuration for the model (from the global configuration, for example).

NOTE: Currently we only map dependencies 'one level' into the configuration hash. Which means the following works as expected:

    MyApp->map_dependencies(
      'Model::Foo' => {
        baz => sub {
          my ($app_or_ctx, $component_name, $config) = @_;
          return ...;
        },
      },
    );

But not this:

    MyApp->map_dependencies(
      'Model::Foo' => {
        baz => {
          bar => sub {
          my ($app_or_ctx, $component_name, $config) = @_;
          return ...;
          },
        },
      },
    );

I'm not sure if I consider this limitation a feature or not... If you have good use cases let me know and I'll consider a fix.

METHODS

This plugin defines the following methods

map_dependencies

Example:

    MyApp->map_dependencies(
      'Model::AnotherModel' => { aaa => 'Model::Foo' },
      'Model::Foo' => {
        bar => 'Model::Bar',
        baz => sub {
          my ($app_or_ctx, $component_name, $config) = @_;
          return ...;
        },
      },
    );

Maps a list of components and dependencies.

map_dependency

Maps a single component to a hashref of dependencies.

CONFIGURATION

This plugin defines the configuration namespace 'Plugin::MapComponentDependencies' and defines the following keys:

map_dependencies

A Hashref where the key is a target component and the value is a hashref of arguments that will be sent to it during initializion.

    MyApp->config(
      'Plugin::MapComponentDependencies' => {
        map_dependencies => {
          'Model::Foo' => {
            bar => 'Model::Bar',
            baz => sub {
              my ($app_or_ctx, $component_name, $from_config_args) = @_;
              return ...;
            },
          },
        },
      },
    );

NOTE: for simplicity you can place your hashref of configuration directly under the plugin namespace.

    MyApp->config(
      'Plugin::MapComponentDependencies' => {
        'Model::Foo' => {
          bar => 'Model::Bar',
          baz => sub {
            my ($app_or_ctx, $component_name, $from_config_args) = @_;
            return ...;
          },
        },
      },
    );

SEE ALSO

Catalyst, Catalyst::Plugin::InjectionHelpers.

AUTHOR

John Napiorkowski email:jjnapiork@cpan.org

COPYRIGHT & LICENSE

Copyright 2015, John Napiorkowski email:jjnapiork@cpan.org

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