[jifty-devel] First pass at an object-model writeup

Jesse Vincent jesse at bestpractical.com
Fri Dec 30 11:37:35 EST 2005


This is in the codebase as Jifty::Manual::ObjectModel.pod.

Does it help clarify things?


=head1 NAME

Jifty::Manual::ObjectModel -- An overview of the Jifty object model

=head1 OVERVIEW

Jifty applications are generally built in a similar way. There's no reason
you I<need> to use the model we've built, but we find it a reasonably
ok way to do things.

This document should serve as a roadmap to the Jifty class library, as 
well as an introduction to the way Jifty applications are put together.

We start with the classes in I<your> application and move on to the bits
of Jifty itself.

If you create a brand new application, let's call it C<MyWeblog>, and
create one model class called C<MyWeblog::Post>, you'll end up with the
following files and directories:

    MyWeblog/
        etc/
            config.yml
        lib/
            MyWeblog/
                Model/
                    Post.pm
                Action/
        bin/
            jifty
    
        web/
            templates/
            static/

        t/
            #some test files.
At least that's the scaffolding Jifty creates for you. Behind the scenes,
Jifty is actually doing a lot more. Rather than create a bunch of little
"stub" classes and libraries for you, Jifty generates them on the fly. It's
always possible to I<actually> create these libraries when you need to customize
the default behavior, but we work really hard to make sure you don't need to.

Right now, Jifty is autocreating libraries, static web pages and web templates.

We're not 100% satisfied with how Jifty autocreates web templates and static pages
and are working to redesign that.

The library you I<see> when creating a Jifty app is:

=over

=item MyWeblog::Model::Post

C<MyWeblog::Model::Post> describes the schema and business logic of your
post class. It uses two namespaces, C<MyWeblog::Model::Post::Schema>
that has actual column definitions and C<MyWeblog::Model::Post> that
contains the (optional) business logic, access control and so on.

=back

That's it. But if you look carefully at C<MyWeblog::Model::Post>, you'll see
the line:

    use base qw/MyWeblog::Record/;

How can that possibly work? There is no C<MyWeblog::Record> class in your
application. And Jifty, while it tries to be a comprehensive framework,
draws the line somewhat short of including application-specific base
classes for every application you might possibly contrive.

The answer lies in L<Jifty::ClassLoader>, a utility module Jifty uses
to create the boring stuff for you when you need it.

It'd certainly be possible for Jifty to create every class you might need
as a file on disk when you first create your application (and indeed
we may decide to do so if enough people yell at us), but when the stub
classes we'd provide are just little shims that inherit from or call
to the Jifty core, it doesn't make much sense to create them before you
need them.  You could build a Jifty application without these shims by
having your model classes inherit directly from Jifty::Record, but then
you'll run into trouble the second you want to add application-specific
code and have to go back and retrofit each and every one of your classes
to use your new base class. It's a little thing, but one that can save
you a bunch of pain and suffering later on.

C<MyWeblog::Record> is the first autogenerated class you'll run into but
probably not the last. A full list of everything Jifty provides for your
new application follows:

You get one each of the these:

=over

=item MyWeblog::Record

This class is, as discussed above, a thin wrapper around
L<Jifty::Record>. You might choose to create your own MyWeblog::Record
if you want to build in custom access control by overriding
L<Jifty::Record/current_user_can> or want to implement methods that
every model class should have access to.

=item MyWeblog::Collection

We haven't talked much about collections yet, but as their name implies,
collections are bundles of L<Jifty::Record> objects that match some set
of criteria. It's relatively uncommon that you'll want to override this,
but if you want the rope, it's here.

=item MyWeblog::Notification 

jC<MyWeblog::Notification> is an app-specific of the
C<Jifty::Notification> email driver. You might want to override this
class if you want to set an application-specific header or footer for
all outgoing email.

=item MyWeblog::CurrentUser

Most every web application that grows past a personal hack eventually
starts to provide personalization, require access control or otherwise
want to know who's currently in the driver's seat. The "current user"
for an application is a first-class object in Jifty. To get user-based
authentication working out of the box, you'll have to override the
default C<MyWeblog::CurrentUser>. (Out of the box, it treats everyone
as the same user.) We're working to generalize the authentication system
we've used in a few Jifty apps so far to the point where it feels "right"
as a core Jifty component, but we're not quite there just yet.

Most of what you'll need to override in C<MyWeblog::CurrentUser> is the
C<_init> function, which needs to load up an application-specific model
class that represents one of your users into its C<user_object> accessor.
To make all this work, you'll also need an application-specific C<Login>
L<Jifty::Action> subclass and likely also a passel of user-management
code.

(And yes, this is the topic of a future generalization and a future
tutorial. At that point, a bunch of this documentation will be extracted
to L<Jifty::CurrentUser>.)

=back

But wait! There's more!  You also get one each of these for your default
model class:

=over

=item MyWeblog::Model::PostCollection

It's no fun having a weblog that only shows you one post at a time,
is it?  Jifty provides you with default L<Jifty::Collection> classes
for every L<Jifty::Record> subclass in your model.  You get all the
standard C<limit>, C<order_by>, C<columns>, paging support and so-on out
of the box, but sometimes when you're going to be getting collections
matching certain criteria often, it makes sense to actually create your
own subclass and start dropping methods in.

=item MyWeblog::Action::CreatePost, MyWeblog::Action::UpdatePost, MyWeblog::Action::DeletePost

One of Jifty's strengths is that it makes it easy to build applications by
tying application-specific controller functions to your model classes and
intuiting what parameters they take by having a look inside the models.

For each C<::Record> class in your model, Jifty creates three
actions, C<Create>,C<Update> and C<Delete>.  They're named,
perhaps a bit unadventureously, C<MyWeblog::Action::CreatePost>,
C<MyWeblog::Action::UpdatePost>, C<MyWeblog::Action::DeletePost>
and inherit directly from C<Jifty::Action::Record::Create>,
C<Jifty::Action::Record::Update> and C<Jifty::Action::Record::Delete>,
respectively. Sometimes, it makes sense to override these default actions
when you want to change the behaviour of one or more of the actions.
One common use is to add or remove AJAX validation or autocompletion
for an argument or to change an argument's default value for webforms.
This, isn't, however the place to start inserting business logic or
access control. That belongs in your model class, which these wrappers
will hand things off to. By putting logic in your actions, you make your
model classes less useful and run into trouble when you want to start
scripting your model outside a web environment.


=back


There's no reason you need to stick with these default "implementations" if they're not meeting your needs. Just create your own classes and Jifty will use your real classes instead.



=cut

1;

-- 


More information about the jifty-devel mailing list