Jifty applications are generally built in a similar way. There's no reason you
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 your application and move on
to the bits of Jifty itself.
If you create a brand new application, let's call it
"MyWeblog", and create one model class
called "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 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 automatically creating libraries, static web
pages and web templates.
We're not 100% satisfied with how Jifty automatically creates web
templates and static pages and are working to redesign that.
The library you see when creating a Jifty app is:
- MyWeblog::Model::Post
- "MyWeblog::Model::Post" describes the
schema and business logic of your post class. It uses two namespaces,
"MyWeblog::Model::Post::Schema" that has
actual column definitions and
"MyWeblog::Model::Post" that contains
the (optional) business logic, access control and so on.
That's it. But if you look carefully at
"MyWeblog::Model::Post", you'll see the
line:
use base qw/MyWeblog::Record/;
How can that possibly work? There is no
"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 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.
"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:
- MyWeblog::Record
- This class is, as discussed above, a thin wrapper around Jifty::Record.
You might choose to create your own
"MyWeblog::Record" if you want to build
in custom access control by overriding "current_user_can" in
Jifty::Record or want to implement methods that every model class should
have access to.
- MyWeblog::Collection
- We haven't talked much about collections yet, but as their name implies,
collections are bundles of 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.
- MyWeblog::Notification
- "MyWeblog::Notification" is an
app-specific implementation of the 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.
- MyWeblog::Dispatcher
- "MyWeblog::Dispatcher" is an
application-specific "dispatcher" class that allows you to write
code that runs when a client makes a request to the server before
Jifty runs actions or renders templates. See
Jifty::Dispatcher for more information about the dispatcher.
- 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 "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
"MyWeblog::CurrentUser" is the
"_init" function, which needs to load
up an application-specific model class that represents one of your users
into its "user_object" accessor. To
make all this work, you'll also need an application-specific
"MyWeblog::Action::Login" 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 Jifty::CurrentUser.)
But wait! There's more! You also get one each of these for your
default model class:
- 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 Jifty::Collection classes for every
Jifty::Record subclass in your model. You get all the standard
"limit",
"order_by",
"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.
- 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 class in your model, Jifty creates three actions,
"Create","Update"
and "Delete". They're named, perhaps a
bit unadventureously,
"MyWeblog::Action::CreatePost",
"MyWeblog::Action::UpdatePost",
"MyWeblog::Action::DeletePost" and
inherit directly from Jifty::Action::Record::Create,
Jifty::Action::Record::Update and 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.
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.