switched eval with Try::Tiny
[catagits/Catalyst-Runtime.git] / lib / Catalyst / IOC / ConstructorInjection.pm
1 package Catalyst::IOC::ConstructorInjection;
2 use Moose;
3 use Try::Tiny;
4 use Catalyst::Utils ();
5 extends 'Bread::Board::ConstructorInjection';
6
7 with 'Bread::Board::Service::WithClass',
8      'Bread::Board::Service::WithParameters',
9      'Bread::Board::Service::WithDependencies';
10
11 has config_key => (
12     is         => 'ro',
13     isa        => 'Str',
14     lazy_build => 1,
15 );
16
17 sub _build_config_key { Catalyst::Utils::class2classsuffix( shift->class ) }
18
19 sub _build_constructor_name { 'COMPONENT' }
20
21 sub get {
22     my $self = shift;
23
24     my $instance;
25
26     my $constructor = $self->constructor_name;
27     my $component   = $self->class;
28     my $config      = $self->param('config')->{ $self->config_key } || {};
29     # FIXME - Is depending on the application name to pass into constructors here a good idea?
30     #         This makes app/ctx split harder I think.. Need to think more here, but I think
31     #         we want to pass the application in as a parameter when building the service
32     #         rather than depending on the app name, so that later, when the app becomes an instance
33     #         then it'll get passed in, and components can stash themselves 'per app instance'
34     my $app_name    = $self->param('application_name');
35
36     # Stash catalyst_component_name in the config here, so that custom COMPONENT
37     # methods also pass it. local to avoid pointlessly shitting in config
38     # for the debug screen, as $component is already the key name.
39     local $config->{catalyst_component_name} = $component;
40
41     unless ( $component->can( $constructor ) ) {
42         # FIXME - make some deprecation warnings
43         return $component;
44     }
45
46     try {
47         $instance = $component->$constructor( $app_name, $config );
48     }
49     catch {
50         Catalyst::Exception->throw(
51             message => qq/Couldn't instantiate component "$component", "$_"/
52         );
53     };
54
55     return $instance
56         if blessed $instance;
57
58     my $metaclass = Moose::Util::find_meta($component);
59     my $method_meta = $metaclass->find_method_by_name($constructor);
60     my $component_method_from = $method_meta->associated_metaclass->name;
61     my $value = defined($instance) ? $instance : 'undef';
62     Catalyst::Exception->throw(
63         message =>
64         qq/Couldn't instantiate component "$component", $constructor() method (from $component_method_from) didn't return an object-like value (value was $value)./
65     );
66 }
67
68 __PACKAGE__->meta->make_immutable;
69
70 no Moose; 1;
71
72 __END__
73
74 =pod
75
76 =head1 NAME
77
78 Catalyst::IOC::ConstructorInjection
79
80 =head1 SYNOPSIS
81
82 =head1 DESCRIPTION
83
84 =head1 AUTHORS
85
86 Catalyst Contributors, see Catalyst.pm
87
88 =head1 COPYRIGHT
89
90 This library is free software. You can redistribute it and/or modify it under
91 the same terms as Perl itself.
92
93 =cut