Remove COMPONENT feature, add tests for making the other features generic from curryi...
[catagits/CatalystX-DynamicComponent.git] / lib / CatalystX / DynamicComponent.pm
CommitLineData
59fc9d16 1package CatalystX::DynamicComponent;
53a42ae0 2use MooseX::Role::Parameterized;
0b07685c 3use MooseX::Types::Moose qw/Str CodeRef ArrayRef/;
046d763d 4use namespace::autoclean;
59fc9d16 5
104abdae 6our $VERSION = 0.000001;
7
53a42ae0 8parameter 'name' => (
0b07685c 9 isa => Str,
53a42ae0 10 required => 1,
11);
12
13parameter 'pre_immutable_hook' => (
0b07685c 14 isa => Str,
53a42ae0 15 predicate => 'has_pre_immutable_hook',
16);
17
cd6bd40d 18parameter 'COMPONENT' => (
0b07685c 19 isa => CodeRef,
cd6bd40d 20 predicate => 'has_custom_component_method',
21);
22
53a42ae0 23role {
24 my $p = shift;
25 my $name = $p->name;
cd6bd40d 26 my $pre_immutable_hook = $p->pre_immutable_hook;
0b07685c 27
53a42ae0 28 method $name => sub {
c52d8688 29 my ($app, $name, $config) = @_;
30
31 $config ||= {};
53a42ae0 32
33 my $appclass = blessed($app) || $app;
34 my $type = $name;
35 $type =~ s/^${appclass}:://; # FIXME - I think there is shit in C::Utils to do this.
36 $type =~ s/::.*$//;
37
38 my $meta = Moose->init_meta( for_class => $name );
279c014c 39
0b07685c 40 my @superclasses = @{ $config->{superclasses} || [] };
41 push(@superclasses, 'Catalyst::' . $type) unless @superclasses;
42 $meta->superclasses(@superclasses);
43
279c014c 44 if (my @roles = @{ $config->{roles}||[] }) {
45 Moose::Util::apply_all_roles( $name, @roles);
46 }
00b934f1 47
cd6bd40d 48 if ($p->has_custom_component_method) {
49 $meta->add_method(COMPONENT => $p->COMPONENT);
50 }
00b934f1 51
cd6bd40d 52 $app->$pre_immutable_hook($meta) if $p->has_pre_immutable_hook;
00b934f1 53
c52d8688 54 foreach my $name (keys %{ $config->{methods}||{} }) {
55 $meta->add_method($name => $config->{methods}->{$name});
549d6abc 56 }
53a42ae0 57 $meta->make_immutable;
58
59 my $instance = $app->setup_component($name);
60 $app->components->{ $name } = $instance;
61 };
62};
59fc9d16 63
641;
65
dc7781e3 66__END__
67
68=head1 NAME
69
70CatalystX::DynamicComponent - Parameterised Moose role providing functionality to build Catalyst components at runtime.
71
72=head1 SYNOPSIS
73
74 package My::DynamicComponentType;
75 use Moose::Role;
76 use namespace::autoclean;
77
78 with 'CatalystX::DynamicComponent' => {
79 name => '_setup_one_of_my_components', # Name of injected method
80 };
81
82 after setup_components => sub { shift->_setup_all_my_components(@_); };
83
84 sub _setup_all_my_components {
85 my ($self, $c) = @_;
86 foreach my $component_name ('MyApp::Component1') {
87 my $component_config = $c->config->{$component_name};
88 # Calling this method creates a component, and registers it in your application
89 $self->_setup_one_of_my_components($component_name, $component_config);
90 }
91 }
92
93=head1 DESCRIPTION
94
95CatalystX::DynamicComponent aims to provide a flexible and reuseable method of building generic
96Catalyst components and registering them with your application.
97
98To give you this flexibility, it is implemented as a parametrised role which curries a
99component builder into your current package at application time.
100
101Authors of specific dynamic component builders are expected to be implemented as application class
102roles which compose this role, but provide their own advice around the C<< setup_compontens >>
103method, and call the curried method from this role once for each component you wish to setup.
104
105=head1 PARAMETERS
106
107=head2 name
108
109B<Required> - The name of the component generator method to curry.
110
111=head2 COMPONENT
112
113Optional, either a L<Class::MOP::Method>, or a plain code ref of a COMPONENT method to apply to
114the dynamically generated package before making it immutable.
115
116=head2 pre_immutable_hook
117
118Optional, method to call after a component has been generated, but before it is made immutable,
119constructed, and added to your component registry.
120
121=head1 CURRIED COMPONENT GENERATOR
122
123=head2 ARGUMENTS
124
125=over
126
127=item $component_name (E.g. C<< MyApp::Controller::Foo >>)
128
129=item $config (E.g. C<< $c->config->{$component_name} >>)
130
131=head2 OPERATION
132
133FIXME
134
135=head1 TODO
136
137=over
138
139=item *
140
141Better default handling of config - by default component should get config from where it normally
142does!
143
144=item *
145
146Abstract handling of role application / class name. This should not just be the component config
147by default.
148
149=item *
150
151Have some actual tests which test just this crap, and not all the other classes together.
152
153=back
154
155=head1 BUGS
156
157Probably plenty, test suite certainly isn't comprehensive.. Patches welcome.
158
159=head1 AUTHOR
160
161Tomas Doran (t0m) <bobtfish@bobtfish.net>
162
163=head1 LICENSE
164
165This code is copyright (c) 2009 Tomas Doran. This code is licensed on the same terms as perl
166itself.
167
168=cut
169