name 'DynamicAppDemo';
all_from 'lib/DynamicAppDemo.pm';
-requires 'Catalyst::Runtime' => '5.80002';
+requires 'Catalyst::Model::Adaptor';
+requires 'Catalyst::Runtime' => '5.80001';
requires 'Catalyst::Plugin::ConfigLoader';
requires 'YAML';
--- /dev/null
+package CatalystX::ModelsFromConfig;
+use Moose::Role;
+use Catalyst::Model::Adaptor ();
+
+requires qw/
+ config
+ setup_components
+ setup_component
+/;
+
+after 'setup_components' => sub { shift->_setup_dynamic_models(@_); };
+
+sub _setup_dynamic_models {
+ my ($app) = @_;
+
+ my $app_name = blessed($app) || $app;
+ my $model_prefix = 'Model::';
+
+ my $model_hash = $app->config || {};
+
+ foreach my $model_name ( grep { /^$model_prefix/ } keys %$model_hash ) {
+ my $model_class_name = $app_name . '::' . $model_name;
+ $app->_setup_dynamic_model( $model_class_name, $model_hash->{$model_name} );
+ }
+}
+
+sub _setup_dynamic_model {
+ my ($app, $name, $config) = @_;
+
+ my $meta = Moose->init_meta( for_class => $name );
+ $meta->superclasses('Catalyst::Model');
+
+ $meta->add_method(
+
+ COMPONENT
+ => sub {
+ my ($model_class_name, $app, $args) = @_;
+
+ my $class = delete $args->{class};
+ Class::MOP::load_class($class);
+
+ $class->new($args);
+ });
+
+ $meta->make_immutable;
+
+ my $instance = $app->setup_component($name);
+ $app->components->{ $name } = $instance;
+}
+
+1;
+
--- /dev/null
+package SomeModelClass;
+use Moose;
+use namespace::clean -except => 'meta';
+
+# Note trivial calling convention.
+# Apply MX::Method::Signatures and MX::Types::Structured to be less lame.
+
+# Introspection should only reflect methods which satisfy the calling convention
+# This is left as an exercise to the reader. :)
+
+sub say_hello {
+ my ($self, $name) = @_;
+ return("Hello $name");
+}
+
+__PACKAGE__->meta->make_immutable;
+
--- /dev/null
+use strict;
+use warnings;
+use Test::More tests => 3;
+
+use DynamicAppDemo;
+
+# Naughty, should make an app instance.
+my $model = DynamicAppDemo->model('One');
+
+ok $model;
+isa_ok $model, 'SomeModelClass';
+is $model->say_hello('world'), 'Hello world';
+