The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
=head1 NAME

Jifty::Manual::Tutorial - Zero to Jifty in a Jiffy

=head1 DESCRIPTION

This tutorial should give you everything you need to
build your first application with Jifty.

=cut

=head1 HOW TO

=head2 The requirements

Here's what you need to have installed -- at least when we write it.

=head2 Installing Jifty

No bones about it. We believe pretty strongly in the DRY (Don't Repeat
Yourself) principle. That's one of the big reasons we love Perl and
CPAN. Jifty makes use of lots of amazing code from CPAN.  At last count,
it directly depended on 100 packages from CPAN.  Most of these libraries
are cross-platform pure-Perl packages and should run great out of the
box on any platform you can get Perl onto.

We've gone to lengths to make sure you don't spend your day
downloading library after library by bundling everything we can inside
the Jifty package.  The Jifty installer is capable of determining what
modules your system needs, and downloading and installing them all in
one go.  Don't worry, it will ask you first before it makes any changes.

On most systems you can use Perl's bundled CPAN module to download
and install Jifty:

  # perl -MCPAN -e'install Jifty'

If you've downloaded a C<.tar.gz> of Jifty, you can do a
manual install:

  # tar xzvf jifty-<version>.tgz
  # cd jifty-<version>
  # perl Makefile.PL
  # make
  # make test
  # make install

If the tests don't pass, we want to hear about it. Please join us
on C<jifty-devel@lists.jifty.org> and report the failure. (See
L</GETTING HELP> below for info on how to join the list.)

=head2 Setting up the Scaffolding

Once you have Jifty happily installed, you're ready to
create your first application.

All you I<really> need to make an application go is a copy of the F<jifty>
command-line tool (inside your new application's F<bin/> directory.)

Of course, it's often helpful to have a bit more structure around to
help guide your work. Jifty comes with tools to build that structure for
you.

Change directory to some place it will be safe to create a new
Jifty application. (Jifty will create a subdirectory for you.)

  # jifty app --name MyWeblog
  Creating new application MyWeblog
  Creating directory MyWeblog/lib
  Creating directory MyWeblog/lib/MyWeblog
  Creating directory MyWeblog/bin
  Creating directory MyWeblog/etc
  Creating directory MyWeblog/doc
  Creating directory MyWeblog/log
  Creating directory MyWeblog/var
  Creating directory MyWeblog/var/mason
  Creating directory MyWeblog/share
  Creating directory MyWeblog/share/po
  Creating directory MyWeblog/share/web
  Creating directory MyWeblog/share/web/templates
  Creating directory MyWeblog/share/web/static
  Creating directory MyWeblog/lib/MyWeblog/Model
  Creating directory MyWeblog/lib/MyWeblog/Action
  Creating directory MyWeblog/t
  Creating configuration file MyWeblog/etc/config.yml

Let's take those one by one.

=over

=item lib

Inside F<lib/> is where all of your application Perl code goes. Your
application generally consists of a set of classes.

=item bin

Inside F<bin/> is F<jifty>, the Jifty command dispatcher. The
most important command is C<jifty server> which starts a standalone
webserver. To find out what commands your F<jifty> comes with, run:

    jifty help

=item etc

Configuration files live in F<etc/>. Jifty generates a basic config
file for your application, F<etc/config.yml>.

=item doc

Jifty can't magically write your documentation for you, but when B<you>
write your docs, put them in F<doc/>.

=item log

Jifty uses L<Log::Log4perl> to configure its logging. By default, it
dumps logs named F<server.log> and F<error.log> into the F<log/> directory.

=item var

Jifty stores cache files here while the server is running. You shouldn't ever
have to touch this directory.

=item share/web/po

Jifty supports internationalization. F<share/web/po/> is where your
translations ("portable object templates") will go.

=item share/web/templates

Though modern Jifty applications are encouraged to use L<Template::Declare>
for templating, we also support L<HTML::Mason> templates. Put your
application's Mason templates in F<share/web/templates/>. Out of the
box, Jifty comes with an application I<skeleton> that it installs in
F<share/web/templates/>. This default application is a convenient way to
get a basic application up and running quickly, but probably needs some
customization as you build a more advanced application.

You can find where Perl stuck Jifty's default templates with:

  perl -MJifty::Util -le 'print Jifty::Util->share_root'

=item share/web/static

Some nontrivial percentage of the content your web application serves
out doesn't need to (or I<shouldn't>) pass through your templating
engine. This includes, for example, images.

Just drop your static files into F<share/web/static/> and Jifty will serve
them out if it can't find a template with the right name.

Out of the box, Jifty comes with plenty of CSS stylesheets, JavaScript
libraries, and even a Pony. Look in F<share/web/static> in the Jifty
distribution, or in the same place Jifty stuck its default templates.

=item lib/MyWeblog/Model

The real base of your application lives in
C<lib/MyWeblog/Model>. Classes here define your application's data
structures and how they relate to each other. Jifty will use your model
classes to set up and upgrade your database's schema when it needs to.

For a full treatment of the Jifty object model see
L<Jifty::Manual::ObjectModel>.

=item lib/MyWeblog/Action

Actions are an API for your model classes. One way you might think of them is
that an action is an HTML form, but generalized. Jifty will generate basic
database-interaction (C<CREATE>, C<READ>, C<UPDATE>, C<DELETE>) B<Actions> for
your B<Models> on-the-fly.

You can also create your own actions for any kind of application logic.

=item t

Jifty starts off your application with a basic harness, but can't yet write
all your tests for you. It does, however, build some simple tests for model
and action classes you generate.

=back

=head2 Building your data model

As you might imagine by the fact that this tutorial application is named
B<MyWeblog>, the example here is a simple weblog application.  Future
tutorials will add authentication, comments, and RSS and Atom feeds.

=head3 Posts

Weblogs tend to center around posts, so it's no surprise that the first model
to create is the C<post>:

  # cd MyWeblog
  # jifty model --name Post
  Writing file /tmp/MyWeblog/lib/MyWeblog/Model/Post.pm
  Writing file /tmp/MyWeblog/t/00-model-Post.t

Great! Now you have a B<Post> model (not that it models anything yet).

Open F<lib/MyWeblog/Model/Post.pm> in your favorite text editor.

You should see something like this:

  use strict;
  use warnings;
  
  package MyWeblog::Model::Post;
  use Jifty::DBI::Schema;
  
  use MyWeblog::Record schema {
  
  };
  
  # Your model-specific methods go here.
  
  1;


Now it's time to tell the model class about what comprises a post. We'll start
out by giving our post a C<body> and a C<title>. (In a future tutorial, the
application will become fully folksonomy-compliant by adding a C<category> and
upgrading that C<category> to a C<tags> table.)

Position your cursor right after:

  use MyWeblog::Record schema {

Add the lines:

  column title =>
        type is 'text',
        label is 'Title',
        default is 'Untitled post';

  column body =>
        type is 'text',
        label is 'Content',
        render as 'Textarea';

Save your model class.

Don't be mistaken, these are lines of actual Perl code. Jifty provides you with
a human-readable language for declaring your models' columns.

=head2 Starting the Jifty application server

You now have a working, if simplistic, application. Start up the Jifty web
server by typing C<jifty server>. For some platforms, you may have to type
C<./bin/jifty server>.

The first thing you'll see is that Jifty notices you have no database, so it
creates one for you. By default, Jifty sets up your application with the SQLite
database engine. If you'd rather use PostgreSQL or MySQL, you need to add some
content to F<etc/config.yml>. See L<Jifty::Config> for a bit more
information.

    # jifty server
    WARN - Application schema has no version in the database.
    WARN - Automatically creating your database.
    INFO - Generating SQL for application MyWeblog...
    INFO - Using MyWeblog::Model::Post, as it appears to be new.
    INFO - Using Jifty::Model::Session, as it appears to be new.
    INFO - Using Jifty::Model::Metadata, as it appears to be new.
    INFO - Set up version 0.0.1, jifty version 0.81208
    INFO - You can connect to your server at http://localhost:8888/

Everything but the last line was database setup information that you'll only
see when Jifty changes your database.

The last line tells you the URL you can go to with your web browser. Have a
look around. Be sure to check out the AJAX-enabled administrative UI, the
online documentation browser, and the Pony.

=head2 Building a user interface

The administrative web does give you everything you need to work with your
application's data. You can create, update, and delete posts. However, it's not
much of a weblog.

=head3 Posting

Let's start building our user interface with a page to create new posts.

Open a new file called F<lib/MyWeblog/View.pm> in your text editor. Make it
look like this:

  package MyWeblog::View;
  use strict;
  use warnings;
  use Jifty::View::Declare -base;
  
  template post => page { title => 'Post Entry' } content {
      my $action = new_action(class => 'CreatePost');
  
      form {
          render_action $action;
          form_submit(label => 'Post');
      }
  };
  
  1;

Jifty provides very concise syntax for generating HTML using
L<Template::Declare>. We'll see plenty more soon.

=head3 Viewing

It's really easy to get a I<basic> listing of entries and a little bit more
complex to get a pretty AJAXified paged list.  Here's how to do both; you can
decide which one works best for you.

=head4 The quick and dirty way

Open your F<lib/MyWeblog/View.pm> file and add this between the C<post>
template and the "1;" at the very end of the file:

  template '/' => page {
      # Get all posts.
      my $posts = MyWeblog::Model::PostCollection->new;
      $posts->unlimit;
  
      # Display each post in a <dl>.
      dl {
          while (my $post = $posts->next) {
              dt { $post->title }
              dd { $post->body  }
          }
      }
  };

Now when you go to C<http://localhost:8888>, you'll be greeted with all of
your blog posts.

=head4 The complex way that gets you lots of cool toys

The I<complex way> involves using one of Jifty's advanced features:
I<Page regions>. These regions let your application reload page sections
independently, either using AJAX on modern high-end browsers or regular GET
requests with downlevel browsers such as C<lynx> and C<w3m>.

The downside of this approach is that each separate region needs to live in
its own template. Happily, this is a good design practice even without regions.

The complex way starts off about the same as the easy way. Replace (or add, if
you shied away from simplicity) the C</> template in your
F<lib/MyWeblog/View.pm>:

  template '/' => page {
      render_region(
          name => 'myweblog-posts',
          path => '/fragments/page_of_posts',
      );
  };

If you're on the ball, you've probably already guessed that you need to create
a template called C</fragments/page_of_posts> in your F<lib/MyWeblog/View.pm>.
Make it contain the following:

  template '/fragments/page_of_posts' => sub {
      # Retrieve the current page argument, defaulting to 1.
      my $page = get('page') || 1;
      
      # Get all posts.
      my $posts = MyWeblog::Model::PostCollection->new;
      $posts->unlimit;
      
      # Display up to three posts on the current page.
      $posts->set_page_info(
          current_page => $page,
          per_page     => 3,
      );
  
      # Notify the user what page they're on if there are multiple.
      if ($posts->pager->last_page > 1) {
          p { "Page $page of " . $posts->pager->last_page }
      }
  
      # Display the current page of posts.
      dl {
          attr { class => 'list' };
  
          while (my $post = $posts->next) {
              dt { $post->title }
              dd { $post->body  }
          }
      };
  
      # Previous page link, the 'page' argument here will set a new value when
      # this region is invoked again.
      if ($posts->pager->previous_page) {
          hyperlink(
              label => 'Previous Page',
              onclick => {
                  args => {
                      page => $posts->pager->previous_page,
                  },
              },
          );
      }
  
      # Next page link.
      if ($posts->pager->next_page) {
          hyperlink(
              label => 'Next Page',
              onclick => {
                  args => {
                      page => $posts->pager->next_page,
                  },
              },
          );
      }
  };

Now fire up your Jifty webserver again. Browse to C</post> and create more than
three posts. Return to the home page and check out the nifty AJAX C<Next Page>
and C<Previous Page> links you now have. Turn off JavaScript or view the page
in C<lynx>, and notice how the AJAX automatically falls-back to page loads for
you. All for free, thanks to Jifty!

=head3 Hey, where did that class come from?

You may have wondered about C<MyWeblog::Model::PostCollection>, since there's
no file called F<PostCollection.pm>. Jifty uses L<Jifty::ClassLoader> to
auto-generate a bunch of classes for you. Of course, you can override these
definitions if you like. See L<Jifty::ClassLoader> for more details.

=head2 Navigation

Of course, having to remember the URL to get to the posting page is a bit
annoying. To get a B<Post> button in the menu, you need to override the default
menus.

We're going to set up a dispatcher for your weblog. A dispatcher handles "doing
things" based on the URL of each incoming request. We can set up additional
menu items by adding them in a "before rendering any template" dispatcher rule.

Open up a new file called F<lib/MyWeblog/Dispatcher.pm> and stick this content
into it:

  package MyWeblog::Dispatcher;
  use strict;
  use warnings;
  use Jifty::Dispatcher -base;
  
  before '*' => run {
      my $top = Jifty->web->navigation;
      $top->child(Home => url => '/');
      $top->child(Post => url => '/post', label => 'Post Article');
  };
  
  1;

Jifty provides nice syntax (yet again!) for declaring dispatcher rules. For
more information about dispatching, see L<Jifty::Dispatcher>. For more
information about the menu system, see the documentation in
L<Jifty::Web::Menu>.

=head2 That's it!

That's just about everything you need to get started building Jifty
applications. We're working hard to make Jifty even easier to use and
to obsolete the I<hard bits> of this tutorial as quickly as we can.

Please join us on the C<jifty-devel> mailing list to talk about how you're
using Jifty or what you find difficult or hard to use about it.

=head1 MORE TUTORIALS

=over 4

=item * Managing your datastore

L<Jifty::Manual::Models>

=item * Doing Stuff With Jifty

L<Jifty::Manual::Actions>

=item * Using page regions

L<Jifty::Manual::PageRegions>

=item * CSS and JS

L<Jifty::Manual::UsingCSSandJS>,
L<Jifty::Manual::JavaScript>

=item * Web Services

See L<Jifty::Manual::TutorialRest> for a quick overview.

=item * Continuations - "There And Back Again"

L<Jifty::Manual::Continuations>

=item * Access Control and Security

L<Jifty::Manual::AccessControl>

=item * Deploying your application in production

L<Jifty::Manual::Deploying>

=item * Upgrading your application's data model

L<Jifty::Manual::Upgrading>

=item * Recipes for common tasks in Jifty

L<Jifty::Manual::Cookbook>

=back

=head1 GETTING HELP

=head2 Online Help

The C<jifty> command-line application comes with builtin help.

  jifty help

  jifty help <command>

If your server is running with administration mode enabled (the
configuration file C<AdminMode> setting is missing or non-zero), you can
click the "Online Docs" link in your browser for an extensive list of
per-module Jifty documentation.

=head2 Joining the mailing list

C<jifty-devel@lists.jifty.org> is where we discuss how we're building Jifty,
what we're having trouble with and so on.

To join the list, send mail to C<jifty-devel-subscribe@lists.jifty.org>.

=head2 Browsing the wiki

We have a wiki! (Actually, the wiki is Jifty's primary website)

Please visit L<http://jifty.org/>, browse and contribute.

The wiki is powered by I<Wifty>, a Wiki built on Jifty. Its code is freely
available from the Jifty subversion repository.

=head1 REPORTING BUGS

Please report bugs in Jifty to C<jifty-devel@lists.jifty.org>.

=cut