Fixed config and subclassing in Catalyst::Component
Matt S Trout [Sun, 7 May 2006 16:23:40 +0000 (16:23 +0000)]
Changes
lib/Catalyst/Component.pm
t/unit_controller_config.t [new file with mode: 0755]

diff --git a/Changes b/Changes
index df57233..6ad4142 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,7 @@
 This file documents the revision history for Perl extension Catalyst.
 
+        - Fix ->config failing to copy _config for subclassing
+
 5.6902  2006-05-04 13:00:00
         - Remove tarballs and OSX metadata files.
 
index da40d5c..5f1e83a 100644 (file)
@@ -100,14 +100,16 @@ sub COMPONENT {
 
 sub config {
     my $self = shift;
-    $self->_config( {} ) unless $self->_config;
+    my $config = $self->_config;
+    unless ($config) {
+        $self->_config( {} );
+        $config = {};
+    }
     if (@_) {
-        my $config = @_ > 1 ? {@_} : $_[0];
-        while ( my ( $key, $val ) = each %$config ) {
-            $self->_config->{$key} = $val;
-        }
+        $config = { %{$config}, %{@_ > 1 ? {@_} : $_[0]} };
+        $self->_config($config);
     }
-    return $self->_config;
+    return $config;
 }
 
 =head2 $c->process()
diff --git a/t/unit_controller_config.t b/t/unit_controller_config.t
new file mode 100755 (executable)
index 0000000..b76b020
--- /dev/null
@@ -0,0 +1,91 @@
+## ============================================================================\r
+## Test to make sure that subclassed controllers (catalyst controllers\r
+## that inherit from a custom base catalyst controller) don't experienc\r
+## any namespace collision in the values under config.\r
+## ============================================================================\r
+\r
+use Test::More tests => 9;\r
+\r
+use strict;\r
+use warnings;\r
+\r
+use_ok('Catalyst');\r
+\r
+## ----------------------------------------------------------------------------\r
+## First We define a base controller that inherits from Catalyst::Controller\r
+## We add something to the config that we expect all children classes to\r
+## be able to find.\r
+## ----------------------------------------------------------------------------\r
+\r
+{\r
+       package base_controller;\r
+       \r
+       use base 'Catalyst::Controller';\r
+       \r
+       __PACKAGE__->config( base_key   => 'base_value' );\r
+}\r
+\r
+## ----------------------------------------------------------------------------\r
+## Next we instantiate two classes that inherit from the base controller.  We\r
+## Add some local config information to these.\r
+## ----------------------------------------------------------------------------\r
+\r
+{\r
+       package controller_a;\r
+\r
+       use base 'base_controller';\r
+       \r
+       __PACKAGE__->config( key_a => 'value_a' );\r
+}\r
+       \r
+       \r
+{\r
+       package controller_b;\r
+\r
+       use base 'base_controller';\r
+\r
+       __PACKAGE__->config( key_b => 'value_b' );\r
+}\r
+\r
+## Okay, we expect that the base controller has a config with one key\r
+## and that the two children controllers inherit that config key and then\r
+## add one more.  So the base controller has one config value and the two\r
+## children each have two.\r
+\r
+## ----------------------------------------------------------------------------\r
+## THE TESTS.  Basically we first check to make sure that all the children of\r
+## the base_controller properly inherit the {base_key => 'base_value'} info\r
+## and that each of the children also has it's local config data and that none\r
+## of the classes have data that is unexpected.\r
+## ----------------------------------------------------------------------------\r
+\r
+\r
+# First round, does everything have what we expect to find? If these tests fail there is something\r
+# wrong with the way config is storing it's information.\r
+\r
+ok( base_controller->config->{base_key} eq 'base_value', 'base_controller has expected config value for "base_key"') or\r
+ diag('"base_key" defined as "'.base_controller->config->{base_key}.'" and not "base_value" in config');\r
+\r
+ok( controller_a->config->{base_key} eq 'base_value', 'controller_a has expected config value for "base_key"') or\r
+ diag('"base_key" defined as "'.controller_a->config->{base_key}.'" and not "base_value" in config');\r
\r
+ok( controller_a->config->{key_a} eq 'value_a', 'controller_a has expected config value for "key_a"') or\r
+ diag('"key_a" defined as "'.controller_a->config->{key_a}.'" and not "value_a" in config');\r
+\r
+ok( controller_b->config->{base_key} eq 'base_value', 'controller_b has expected config value for "base_key"') or\r
+ diag('"base_key" defined as "'.controller_b->config->{base_key}.'" and not "base_value" in config');\r
\r
+ok( controller_b->config->{key_b} eq 'value_b', 'controller_b has expected config value for "key_b"') or\r
+ diag('"key_b" defined as "'.controller_b->config->{key_b}.'" and not "value_b" in config');\r
+\r
+# second round, does each controller have the expected number of config values? If this test fails there is\r
+# probably some data collision between the controllers.\r
+\r
+ok( scalar(keys %{base_controller->config}) == 1, 'base_controller has the expected number of config values') or\r
+ diag("base_controller should have 1 config value, but it has ".scalar(keys %{base_controller->config}));\r
\r
+ok( scalar(keys %{controller_a->config}) == 2, 'controller_a has the expected number of config values') or\r
+ diag("controller_a  should have 2 config value, but it has ".scalar(keys %{base_controller->config}));\r
\r
+ok( scalar(keys %{controller_b->config}) == 2, 'controller_b has the expected number of config values') or\r
+ diag("controller_a should have 2 config value, but it has ".scalar(keys %{base_controller->config}));\r