predicate => 'has_configfile',
);
+# overridable in consuming class or role to provide a default value
+# called before instantiation, so must be a class method!
+sub _get_default_configfile { }
+
sub new_with_config {
my ($class, %opts) = @_;
$configfile = $opts{configfile}
}
else {
- my $cfmeta = $class->meta->find_attribute_by_name('configfile');
+ # This would only succeed if the consumer had changed the name of the
+ # reader method, and defined a new configfile sub in its place
$configfile = try { to_File($class->configfile) };
- $configfile ||= $cfmeta->default if $cfmeta->has_default;
+
+ # this is gross, but since a lot of users have swapped in their own
+ # default subs, we have to keep calling it rather than calling a
+ # builder sub directly - and it might not even be a coderef either
+ my $cfmeta = $class->meta->find_attribute_by_name('configfile');
+ $configfile ||= $cfmeta->default;
+
if (ref $configfile eq 'CODE') {
- $configfile = &$configfile($class);
+ $configfile = $configfile->($class);
}
+
+ $configfile ||= $class->_get_default_configfile;
+
+ $opts{$cfmeta->init_arg} = $configfile if defined $configfile;
}
if (defined $configfile) {
--- /dev/null
+use strict;
+use warnings;
+
+use Test::More tests => 20;
+use Test::Fatal;
+use Test::Deep '!blessed';
+use Test::NoWarnings 1.04 ':early';
+use Scalar::Util 'blessed';
+
+my %loaded_file;
+my %constructor_args;
+my %default_sub;
+
+
+# nothing special going on here
+{
+ package Generic;
+ use Moose;
+ with 'MooseX::SimpleConfig';
+ sub get_config_from_file { }
+}
+
+is(
+ exception {
+ my $obj = Generic->new_with_config;
+ is($obj->configfile, undef, 'no configfile set');
+ },
+ undef,
+ 'no exceptions',
+);
+
+
+# this is a classic legacy usecase that we must continue to support
+{
+ package OverriddenDefault;
+ use Moose;
+ with 'MooseX::SimpleConfig';
+ sub get_config_from_file
+ {
+ my ($class, $file) = @_;
+ $loaded_file{$file}++;
+ +{}
+ }
+ has '+configfile' => (
+ default => 'OverriddenDefault file',
+ );
+}
+
+is(
+ exception {
+ my $obj = OverriddenDefault->new_with_config;
+ is($obj->configfile, 'OverriddenDefault file', 'configfile set via overridden default');
+ is($loaded_file{'OverriddenDefault file'}, 1, 'correct file was loaded from');
+ },
+ undef,
+ 'no exceptions',
+);
+
+
+# legacy usecase, and configfile init_arg has been changed
+{
+ package OverriddenDefaultAndChangedName;
+ use Moose;
+ with 'MooseX::SimpleConfig';
+ sub get_config_from_file
+ {
+ my ($class, $file) = @_;
+ $loaded_file{$file}++;
+ +{}
+ }
+ has '+configfile' => (
+ init_arg => 'my_configfile',
+ default => 'OverriddenDefaultAndChangedName file',
+ );
+ around BUILDARGS => sub {
+ my ($orig, $class) = (shift, shift);
+ my $args = $class->$orig(@_);
+ $constructor_args{$class} = $args;
+ };
+}
+
+is(
+ exception {
+ my $obj = OverriddenDefaultAndChangedName->new_with_config;
+ is($obj->configfile, blessed($obj) . ' file', 'configfile set via overridden default');
+ cmp_deeply(
+ $constructor_args{blessed($obj)},
+ { my_configfile => blessed($obj) . ' file' },
+ 'correct constructor args passed',
+ );
+ is($loaded_file{blessed($obj) . ' file'}, 1, 'correct file was loaded from');
+ },
+ undef,
+ 'no exceptions',
+);
+
+
+# newly-supported overridable method for configfile default
+{
+ package WrapperSub;
+ use Moose;
+ with 'MooseX::SimpleConfig';
+ sub get_config_from_file
+ {
+ my ($class, $file) = @_;
+ $loaded_file{$file}++;
+ +{}
+ }
+
+ sub _get_default_configfile {
+ my $class = shift;
+ $default_sub{$class}++;
+ $class . ' file'
+ }
+
+ around BUILDARGS => sub {
+ my ($orig, $class) = (shift, shift);
+ my $args = $class->$orig(@_);
+ $constructor_args{$class} = $args;
+ };
+}
+
+is(
+ exception {
+ my $obj = WrapperSub->new_with_config;
+ is($obj->configfile, blessed($obj) . ' file', 'configfile set via overridden sub');
+ cmp_deeply(
+ $constructor_args{blessed($obj)},
+ { configfile => blessed($obj) . ' file' },
+ 'correct constructor args passed',
+ );
+ is($default_sub{blessed($obj)}, 1, 'default sub called just once');
+ is($loaded_file{blessed($obj) . ' file'}, 1, 'correct file was loaded from');
+ },
+ undef,
+ 'no exceptions',
+);
+
+
+# newly-supported overridable method for configfile default, and configfile
+# init_arg has been changed
+{
+ package WrapperSubAndChangedName;
+ use Moose;
+ with 'MooseX::SimpleConfig';
+ has '+configfile' => (
+ init_arg => 'my_configfile',
+ );
+ sub get_config_from_file
+ {
+ my ($class, $file) = @_;
+ $loaded_file{$file}++;
+ +{}
+ }
+
+ sub _get_default_configfile {
+ my $class = shift;
+ $default_sub{$class}++;
+ $class . ' file'
+ }
+
+ around BUILDARGS => sub {
+ my ($orig, $class) = (shift, shift);
+ my $args = $class->$orig(@_);
+ $constructor_args{$class} = $args;
+ };
+}
+
+is(
+ exception {
+ my $obj = WrapperSubAndChangedName->new_with_config;
+ is($obj->configfile, blessed($obj) . ' file', 'configfile set via overridden sub');
+ cmp_deeply(
+ $constructor_args{blessed($obj)},
+ { my_configfile => blessed($obj) . ' file' },
+ 'correct constructor args passed',
+ );
+ is($default_sub{blessed($obj)}, 1, 'default sub called just once');
+ is($loaded_file{blessed($obj) . ' file'}, 1, 'correct file was loaded from');
+ },
+ undef,
+ 'no exceptions',
+);
+