[jifty-devel] Customizing the Jifty Login plugin.

John Peacock jpeacock at rowman.com
Thu Nov 30 19:50:55 EST 2006

Wolfgang Kinkeldei wrote:
>> Error in /home/w3pm/perl/lib/site_perl/5.8.8/Jifty/Action/Record.pm
>> line 149 Can't locate object method "homepage" via package
>> "Jifty::Plugin::Login::Model::User"
>> I think Jifty grabs my User(Model) but not my Signup(Action). I could
>> edit the Login dispatcher, but I don't want to touch the Login. Please
>> show me the recipe if you have.

There are a couple of things going on behind the scenes that are not immediately
evident.  If you just add the Login plugin to an application (and don't override
anything), Jifty::Plugin->new() creates virtual classes in the application
namespace that are wrappers of the Jifty::Plugin classes, inheriting all of
their methods using the normal Perl inheritance model.

However, if you override the Jifty::Plugin classes with your own, those classes
take over, so it should be possible to extend the base classes.  But somewhere
in the interaction with Module::Pluggable, the inheritance is breaking down and
I have not been able to figure out where.

> I tested a bit to see what happens. If you create a class
> "App::Model::User" having "Jifty::Plugin::Login::Model::User" as base
> and append fields to the schema, the database is created right. fine.

This shows that the inherited classes are correctly being called here.

> After an action of class "App::Action::CreateUser" is build via
> Jifty->web->new_action, this action reports its "record_class" to be
> "Jifty::Plugin::Login::Model::User" instead of your own class
> "App::Model::User". 

This is where things go wrong.  I /think/ that the problem is that the schema
class is working (so the database gets the write table structure), but that the
implementation class is still inheriting the base class.  I just can't track
down where that is happening.  So much is happening on the fly as the app
executes that it is very tricky to figure out where things are happening.

> I am not quite sure, but I think this is a
> side-effect of Module::Pluggable, as I did never see a
> "App::Action::CreateUser" to get created by "Jifty::ClassLoader".

There will actually be three (in the single plugin case) "ClassLoader" entries
in @INC:

1) the one providing the application classes/methods;
2) the one providing access the Login plugin classes/methods;
3) the one providing access to the base Jifty classes/methods.

Those are listed, in that order, in @INC, so the normal inheritance walk finds
the first existing class that implements that object.  The part that makes that
tricky is that both #2 and #3 are created on the fly (meaning they aren't there
until they need to be).  This is the Module::Pluggable piece that makes things
so difficult to debug.

> However, the Action modules in the Login plugin explicitly use the
> "Jifty::Plugin::Login::Action::..." actions, so they will not work on
> expanded models.

No, the inherited class (whether implied or explicit) should be calling them as
App::Action::.. and the Perl inheritance rules will dispatch the actual method
with the App object as $self.

I just checked in a very small patch that deals with a different limitation of
the Login plugin: Login::Action::Signup would delete unknown args that were
submitted, but it only "knew" about the fields which were in the default class
(so it would nuke extended attributes).  I've deleted this and also made the
email_confirmed and auth_token fields "Unrendered", which has almost exactly the
same effect.  We should still have a way for an inherited class to validate the
submitted args (to prevent form injection hacks).


John Peacock
Director of Information Research and Technology
Rowman & Littlefield Publishing Group
4501 Forbes Blvd
Suite H
Lanham, MD 20706
301-459-3366 x.5010
fax 301-429-5747

More information about the jifty-devel mailing list