[Jifty-commit] r4581 - in jifty/trunk: . lib/Jifty/Script t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Model t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model t/TestApp-Plugin-AppPluginHasModels/t

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Fri Nov 30 10:49:54 EST 2007


Author: sterling
Date: Fri Nov 30 10:49:47 2007
New Revision: 4581

Added:
   jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Model/Texture.pm
   jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Model/Wallpaper.pm
   jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model/Texture.pm
   jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/t/app-model-ref.t
   jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/t/app-model.t
Modified:
   jifty/trunk/   (props changed)
   jifty/trunk/lib/Jifty/ClassLoader.pm
   jifty/trunk/lib/Jifty/Script/Schema.pm
   jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model/Color.pm
   jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/t/plugin-model.t

Log:
 r14295 at dynpc145:  andrew | 2007-11-30 09:48:06 -0600
 Add support for application overridden models which gives us:
  (1) References from plugins to app models with less pain.
  (2) An easier implementation path in cases where mixins are just extra work.
  (3) Allows application flexibility to modify plugin models.
  (4) Consistency with the way apps may override actions an notifications.


Modified: jifty/trunk/lib/Jifty/ClassLoader.pm
==============================================================================
--- jifty/trunk/lib/Jifty/ClassLoader.pm	(original)
+++ jifty/trunk/lib/Jifty/ClassLoader.pm	Fri Nov 30 10:49:47 2007
@@ -109,6 +109,12 @@
 
 An empty class that descends from L<Jifty::Handle> is created.
 
+=item I<Application>::Model::I<Something>
+
+If C<I<Application>::Plugin::I<Plugin>::Model::I<Something>> exists and is a model class, then it creates a subclass of it named C<I<Application>::Model::I<Something>> for the local application.
+
+This allows an application to customize a model provided by a subclass (or choose not to). Plugins should be written to use the application's version.
+
 =item I<Application>::Model::I<Something>Collection
 
 If C<I<Application>::Model::I<Something>> is a valid model class, then
@@ -177,7 +183,7 @@
                 . "use Jifty::View::Declare -base; sub _autogenerated { 1 };\n"
             );
     } 
-    
+
     # Autogenerate the Collection class for a Model
     elsif ( $module =~ /^(?:$base)::Model::([^\.]+)Collection$/ ) {
         return $self->return_class(
@@ -234,11 +240,11 @@
     # type of notification or action.
     #
     # This allows the application to customize what happens on a plugin action
-    # or customize the email notification sent by a plugin. 
+    # or model or customize the email notification sent by a plugin. 
     #
     # However, this depends on the plugin being well-behaved and always using
-    # the application version of actions and notifications rather than trying
-    # to use the plugin class directly.
+    # the application version of actions, models, and notifications rather than
+    # trying to use the plugin class directly.
     #
     # Of course, if the class loader finds such a case, then the application
     # has not chosen to override it and we're generating the empty stub to take
@@ -251,7 +257,7 @@
     # Plugin::Model::Thing instead.
     
     # Requesting an application override of a plugin action or notification?
-    if ( $module =~ /^(?:$base)::(Action|Notification)::(.*)$/x and not grep {$_ eq $base} map {ref} Jifty->plugins ) {
+    if ( $module =~ /^(?:$base)::(Action|Model|Notification)::(.*)$/x and not grep {$_ eq $base} map {ref} Jifty->plugins ) {
         my $type = $1;
         my $item = $2;
 
@@ -260,12 +266,23 @@
             next if ($plugin eq $base);
             my $class = $plugin."::".$type."::".$item;
 
-            # Found it! Generate the empty stub.
+            # Found it!
             if (Jifty::Util->try_to_require($class) ) {
+
+                # Models need to load their other stuff, but to prevent deep
+                # recursion, this must happen after the class is compiled.
+                my $module_suffix = '';
+                $module_suffix = "Jifty->class_loader"
+                               . "->_require_model_related_classes("
+                               . "'$module');\n"
+                    if $type eq 'Model';
+
+                # Generate the empty stub
                 return $self->return_class(
                         "package $module;\n"
                         . "use base qw/$class/;\n"
                         . "sub _autogenerated { 1 };\n"
+                        . $module_suffix
                     );
             }
         }

Modified: jifty/trunk/lib/Jifty/Script/Schema.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Script/Schema.pm	(original)
+++ jifty/trunk/lib/Jifty/Script/Schema.pm	Fri Nov 30 10:49:47 2007
@@ -249,13 +249,15 @@
         $pluginvs{ $plugin_class } = version->new( $plugin->version );
     }
 
+    MODEL:
     for my $model ( @models) {
+        my $plugin_root = Jifty->app_class('Plugin').'::';
+
         # TODO XXX FIXME:
         #   This *will* try to generate SQL for abstract base classes you might
         #   stick in $AC::Model::.
         if ($model->can('since')) {
             my $app_class   = Jifty->app_class;
-            my $plugin_root = Jifty->app_class('Plugin');
 
             my $installed_version = 0;
 
@@ -280,10 +282,22 @@
             if ($installed_version < $model->since) {
                 # XXX Is this message correct? 
                 $log->info("Skipping $model, as it should already be in the database");
-                next;
+                next MODEL;
             }
         }
 
+        if ($model =~ /^(?:Jifty::Plugin::|$plugin_root)/
+                and $model =~ /::Model::(.*)$/) {
+            my $model_name = $1;
+
+            # Check to make sure this model is not overridden in the app,
+            # in such cases we don't want to try to create the same table
+            # twice, so let the app model do it rather than the plugin
+            my $app_model = Jifty->app_class($model_name);
+            $app_model->require;
+            next MODEL unless $app_model->can('_autogenerated');
+        }
+
         $log->info("Using $model, as it appears to be new.");
 
         $self->schema->_check_reserved($model)

Added: jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Model/Texture.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Model/Texture.pm	Fri Nov 30 10:49:47 2007
@@ -0,0 +1,14 @@
+use strict;
+use warnings;
+
+package TestApp::Plugin::AppPluginHasModels::Model::Texture;
+use base qw/ TestApp::Plugin::AppPluginHasModels::Plugin::MyAppPlugin::Model::Texture /;
+
+use Jifty::DBI::Schema;
+use TestApp::Plugin::AppPluginHasModels::Record schema {
+    # yeah, i know this is a lame schema...
+    column exemplar =>
+        references TestApp::Plugin::AppPluginHasModels::Model::Wallpaper;     
+};
+
+1;

Added: jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Model/Wallpaper.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Model/Wallpaper.pm	Fri Nov 30 10:49:47 2007
@@ -0,0 +1,18 @@
+use strict;
+use warnings;
+
+package TestApp::Plugin::AppPluginHasModels::Model::Wallpaper;
+use Jifty::DBI::Schema;
+
+use TestApp::Plugin::AppPluginHasModels::Record schema {
+    column name =>
+        type is 'text';
+
+    column color =>
+        references TestApp::Plugin::AppPluginHasModels::Model::Color;
+
+    column texture =>
+        references TestApp::Plugin::AppPluginHasModels::Model::Texture;
+};
+
+1;

Modified: jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model/Color.pm
==============================================================================
--- jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model/Color.pm	(original)
+++ jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model/Color.pm	Fri Nov 30 10:49:47 2007
@@ -12,4 +12,6 @@
         type is 'text';
 };
 
+sub table { 'myappplugin_colors' }
+
 1;

Added: jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model/Texture.pm
==============================================================================
--- (empty file)
+++ jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/lib/TestApp/Plugin/AppPluginHasModels/Plugin/MyAppPlugin/Model/Texture.pm	Fri Nov 30 10:49:47 2007
@@ -0,0 +1,12 @@
+use strict;
+use warnings;
+
+package TestApp::Plugin::AppPluginHasModels::Plugin::MyAppPlugin::Model::Texture;
+use Jifty::DBI::Schema;
+
+use TestApp::Plugin::AppPluginHasModels::Plugin::MyAppPlugin::Record schema {
+    column name =>
+        type is 'text';
+};
+
+1;

Added: jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/t/app-model-ref.t
==============================================================================
--- (empty file)
+++ jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/t/app-model-ref.t	Fri Nov 30 10:49:47 2007
@@ -0,0 +1,76 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+=head1 DESCRIPTION
+
+A basic test harness for the Wallpaper model.
+
+=cut
+
+use lib 't/lib';
+use Jifty::SubTest;
+use Jifty::Test tests => 20;
+
+# Make sure we can load the model
+use_ok('TestApp::Plugin::AppPluginHasModels::Model::Wallpaper');
+
+# Grab a system user
+my $system_user = TestApp::Plugin::AppPluginHasModels::CurrentUser->superuser;
+ok($system_user, "Found a system user");
+
+# Try a color create
+my $color = TestApp::Plugin::AppPluginHasModels::Model::Color->new(current_user => $system_user);
+my ($color_id) = $color->create( name => 'Blue' );
+ok($color_id, 'we have a color');
+
+# Try a texture create
+my $texture = TestApp::Plugin::AppPluginHasModels::Model::Texture->new(current_user => $system_user);
+my ($texture_id) = $texture->create( name => 'Rough' );
+ok($texture_id, 'we have a texture');
+
+# Try testing a create
+my $o = TestApp::Plugin::AppPluginHasModels::Model::Wallpaper->new(current_user => $system_user);
+my ($id) = $o->create(
+    name => 'Plaid',
+    color => $color,
+    texture => $texture,
+);
+ok($id, "Wallpaper create returned success");
+ok($o->id, "New Wallpaper has valid id set");
+is($o->id, $id, "Create returned the right id");
+is($o->name, 'Plaid', 'name is Plaid');
+is($o->color->name, 'Blue', 'color is Blue');
+is($o->texture->name, 'Rough', 'texture is Rough');
+
+# And another
+$o->create();
+ok($o->id, "Wallpaper create returned another value");
+isnt($o->id, $id, "And it is different from the previous one");
+
+# Searches in general
+my $collection = TestApp::Plugin::AppPluginHasModels::Model::WallpaperCollection->new(current_user => $system_user);
+$collection->unlimit;
+is($collection->count, 2, "Finds two records");
+
+# Searches in specific
+$collection->limit(column => 'id', value => $o->id);
+is($collection->count, 1, "Finds one record with specific id");
+
+# Delete one of them
+$o->delete;
+$collection->redo_search;
+is($collection->count, 0, "Deleted row is gone");
+
+# And the other one is still there
+$collection->unlimit;
+is($collection->count, 1, "Still one left");
+
+# Needed for the action tests...
+Jifty::Test->web;
+
+# Make sure actions are available
+isa_ok($collection->as_search_action, 'TestApp::Plugin::AppPluginHasModels::Action::SearchWallpaper');
+isa_ok($o->as_create_action, 'TestApp::Plugin::AppPluginHasModels::Action::CreateWallpaper');
+isa_ok($o->as_update_action, 'TestApp::Plugin::AppPluginHasModels::Action::UpdateWallpaper');
+isa_ok($o->as_delete_action, 'TestApp::Plugin::AppPluginHasModels::Action::DeleteWallpaper');

Added: jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/t/app-model.t
==============================================================================
--- (empty file)
+++ jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/t/app-model.t	Fri Nov 30 10:49:47 2007
@@ -0,0 +1,62 @@
+#!/usr/bin/env perl
+use warnings;
+use strict;
+
+=head1 DESCRIPTION
+
+A basic test harness for the Color model.
+
+=cut
+
+use lib 't/lib';
+use Jifty::SubTest;
+use Jifty::Test tests => 16;
+
+# Make sure we can load the model
+use_ok('TestApp::Plugin::AppPluginHasModels::Model::Color');
+
+# Grab a system user
+my $system_user = TestApp::Plugin::AppPluginHasModels::CurrentUser->superuser;
+ok($system_user, "Found a system user");
+
+# Try testing a create
+my $o = TestApp::Plugin::AppPluginHasModels::Model::Color->new(current_user => $system_user);
+my ($id) = $o->create();
+ok($id, "Color create returned success");
+ok($o->id, "New Color has valid id set");
+is($o->id, $id, "Create returned the right id");
+
+# Does it use a prefixed table
+is($o->table, 'myappplugin_colors', 'custom plugin table name');
+
+# And another
+$o->create();
+ok($o->id, "Color create returned another value");
+isnt($o->id, $id, "And it is different from the previous one");
+
+# Searches in general
+my $collection = TestApp::Plugin::AppPluginHasModels::Model::ColorCollection->new(current_user => $system_user);
+$collection->unlimit;
+is($collection->count, 2, "Finds two records");
+
+# Searches in specific
+$collection->limit(column => 'id', value => $o->id);
+is($collection->count, 1, "Finds one record with specific id");
+
+# Delete one of them
+$o->delete;
+$collection->redo_search;
+is($collection->count, 0, "Deleted row is gone");
+
+# And the other one is still there
+$collection->unlimit;
+is($collection->count, 1, "Still one left");
+
+# Needed for the action tests...
+Jifty::Test->web;
+
+# Make sure actions are available
+isa_ok($collection->as_search_action, 'TestApp::Plugin::AppPluginHasModels::Action::SearchColor');
+isa_ok($o->as_create_action, 'TestApp::Plugin::AppPluginHasModels::Action::CreateColor');
+isa_ok($o->as_update_action, 'TestApp::Plugin::AppPluginHasModels::Action::UpdateColor');
+isa_ok($o->as_delete_action, 'TestApp::Plugin::AppPluginHasModels::Action::DeleteColor');

Modified: jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/t/plugin-model.t
==============================================================================
--- jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/t/plugin-model.t	(original)
+++ jifty/trunk/t/TestApp-Plugin-AppPluginHasModels/t/plugin-model.t	Fri Nov 30 10:49:47 2007
@@ -27,7 +27,7 @@
 is($o->id, $id, "Create returned the right id");
 
 # Does it use a prefixed table
-is($o->table, 'testapp_plugin_apppluginhasmodels_plugin_myappplugin_colors', 'plugin table prefix');
+is($o->table, 'myappplugin_colors', 'custom plugin table name');
 
 # And another
 $o->create();


More information about the Jifty-commit mailing list