MooseX-ConfigCascade

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

Changes
Makefile.PL
MANIFEST
README
t/00_file.t
t/01_conf.t
t/02_error.t
t/03_cascade.t
t/04_moose.t
t/05_parser.t
t/data/arbitrary.conf
t/data/bottle.json
t/data/widget.json
t/data/widget.yml
t/lib/ConfigCascade/Test/Book.pm
t/lib/ConfigCascade/Test/BottleBox.pm
t/lib/ConfigCascade/Test/Bottle.pm
t/lib/ConfigCascade/Test/BottleTop.pm

lib/MooseX/ConfigCascade.pm  view on Meta::CPAN

package MooseX::ConfigCascade;

our $VERSION = '0.02';

use Moose::Role;
use MooseX::ConfigCascade::Util;

has cascade_util => (is => 'ro', lazy => 1, isa => 'MooseX::ConfigCascade::Util', default => sub{
    MooseX::ConfigCascade::Util->new(
        _to_set => $_[0],
        _role_name => __PACKAGE__
    );
});


sub BUILD{}
after BUILD => sub{
    my ($self,$args) = @_;
    my $util = $self->cascade_util;
    foreach my $k (keys %$args){ $util->_args->{$k} = 1 }
    $util->_parse_atts;
};


1;
__END__
=head1 NAME

MooseX::ConfigCascade - Set initial accessor values of your whole Moose-based project from a single config file

lib/MooseX/ConfigCascade.pm  view on Meta::CPAN



=head1 METHODS

Remember B<not> to C<use MooseX::ConfigCascade>. It's a role, so you should state:

    with 'MooseX::ConfigCascade';

When you do this, a single new attribute is added to your class:

=head2 cascade_util

This is a L<MooseX::ConfigCascade::Util> object, which has 3 utility methods. So once you added the L<MooseX::ConfigCascade> role to your package, you can do:

    my $object = My::Package->new;

    $object->cascade_util->conf;     # access the config hash directly
    $object->cascade_util->path;     # the path to the config file (if any)
    $object->cascade_util->parser;   # the code ref to the subroutine which parses your config file

Note C<conf>, C<path> and C<parser> are all B<class attributes> of L<MooseX::ConfigCascade::Util>. That means it is intended that you generally set them by calling the class directly:

    MooseX::ConfigCascade::Util->path( '/path/to/config.yaml' );

    # etc ...

so you may not ever need to use C<cascade_util> at all. However, you may find it useful that you can access the full config from anywhere in your project:

    $whatever_object->cascade_util->conf;

See the documentation for L<MooseX::ConfigCascade::Util> for information about these methods.


=head1 SEE ALSO

L<MooseX::ConfigCascade::Util>
L<Moose>
L<MooseX::ClassAttribute>

lib/MooseX/ConfigCascade/Util.pm  view on Meta::CPAN

                    $tc->is_a_type_of('ArrayRef') ||
                    $tc->is_a_type_of('Bool')){

                    $att->set_value($to_set,$att_set->{$att_name});

                } elsif ( 
                        $tc->is_a_type_of('Object')
                    &&  $to_set->$att_name->DOES( $self->_role_name )
                ){
                
                        my $util = $to_set->$att_name->cascade_util;
                        $util->_att_name( $att_name );
                        unshift @{$util->_stack}, $att_set;
                        $util->_parse_atts;
                }
            }
        }
    }
}

1;

t/00_file.t  view on Meta::CPAN

use ConfigCascade::Test::RW_Widget;
use ConfigCascade::Test::RO_Widget;
BEGIN { use_ok('MooseX::ConfigCascade::Util') };

my $test_data = ConfigCascade::Test::Data->new;
my $expected = $test_data->expected;
# with path not set

my $widget = ConfigCascade::Test::RW_Widget->new;

isa_ok( $widget->cascade_util, 'MooseX::ConfigCascade::Util', "->cascade_util");
is( $widget->cascade_util->path, undef, '->cascade_util->path not set by default');
isa_ok( $widget->cascade_util->conf, 'HASH', '->conf with ->path not set');
is( scalar( keys %{$widget->cascade_util->conf}), 0, '->conf is an empty HashRef with ->path not set');


foreach my $type ( $test_data->types ){
    
    my $accessor = $type.'_no_default';
    ok( ! defined $widget->$accessor, "->$accessor initialised correctly" );

    foreach my $create_mode ( $test_data->modes ){
        next if $create_mode=~/no_default/;

t/00_file.t  view on Meta::CPAN

    MooseX::ConfigCascade::Util->path( $path );

    is( MooseX::ConfigCascade::Util->path, $path, '->path gives correct return value' );


    foreach my $rwo ( $test_data->rwo ){

        my $package = "ConfigCascade::Test::".uc($rwo)."_Widget";
        $widget = $package->new;

        isa_ok( $widget->cascade_util, 'MooseX::ConfigCascade::Util', "($rwo) ->cascade_util");
        is( $widget->cascade_util->path, $path, "($rwo) ->cascade_util->path behaves as class attribute");

        my $conf = $widget->cascade_util->conf;

        isa_ok( $conf, 'HASH', "($rwo) ->conf" );

        my $expected_conf = $expected->{conf}->( $filetype );

        is_deeply( $conf, $expected_conf, "($rwo) conf loaded correctly" );

        foreach my $type ( $test_data->types ){
            
            my $accessor = $type.'_no_default';

t/01_conf.t  view on Meta::CPAN

            my $modified_val = $modify->{$type}->( $accessor );
            $conf{$package}{$accessor} = $modified_val;
            

            MooseX::ConfigCascade::Util->conf( \%conf );
            my $widget = $package->new;

            foreach my $att ($widget->meta->get_all_attributes){

                my $att_name = $att->name;
                next if $att_name eq 'cascade_util';

                if ( $att_name eq $accessor ){
                    is_deeply( $widget->$att_name, $modified_val, "($rwo, $accessor modified) ->$att_name correctly loaded with modified value" );
                } else {
                    is_deeply( $widget->$att_name, $base_conf{$package}{$att_name}, "($rwo, $accessor modified) ->$att_name correctly loaded without being modified" );
                }
            }
        }
    }
}



( run in 0.265 second using v1.01-cache-2.11-cpan-3cd7ad12f66 )