[Catalyst-commits] r7240 -
trunk/examples/CatalystAdvent/root/2007/pen
claco at dev.catalyst.perl.org
claco at dev.catalyst.perl.org
Thu Dec 6 02:45:00 GMT 2007
Author: claco
Date: 2007-12-06 02:45:00 +0000 (Thu, 06 Dec 2007)
New Revision: 7240
Modified:
trunk/examples/CatalystAdvent/root/2007/pen/6.pod
Log:
Added mango overview
Modified: trunk/examples/CatalystAdvent/root/2007/pen/6.pod
===================================================================
--- trunk/examples/CatalystAdvent/root/2007/pen/6.pod 2007-12-06 00:00:25 UTC (rev 7239)
+++ trunk/examples/CatalystAdvent/root/2007/pen/6.pod 2007-12-06 02:45:00 UTC (rev 7240)
@@ -1,5 +1,301 @@
-=head1 Mango Overview
+=head1 A Future Look at Mango
+Mango is an attempt to combine the best of Catalyst, Handel and DBIx::Class into
+an ecommerce framework giving a jump start to anyone that needs to sell products
+online using our favorite MVC framework. Like Handel and to an extent Catalyst,
+the main goal of Mango is to have as many reusable, non web-specific parts as
+possible while simultaniously acknowledging that it can never be the one
+solution that fits all. It's a framework, not a solution. Mango is also an
+exercise in trying to round off some of the rough corners that aggravate me
+about Catalyst web development in general.
+
+=head2 Installable And Updatable
+
+One of the things about Catalyst applications that bugs me is that they aren't
+really installable. Sure, you can run C<perl Makefile.PL & make install> on
+your shiny new MyApp but odd things happen. Where did that root directory go?
+Where's my templates? Why can't server.pl find my Makefile.PL. As a solution to
+that, most people take the unpack-and-run approach. But as soon you need to
+customize that application [built by someone else], now you have to merge your
+changes into each new release on your machine. That's a drag too.
+
+In Mango, the goal is to have to have everything that ships in the dist
+installed into the perl auto paths, including the default templates, forms,
+stylesheets, etc using C<File::ShareDir>:
+
+ perl Makefile.PL
+ make install
+ ...
+ /sw/lib/perl5/5.8.6/auto/Mango/forms/admin/users/create.yml
+ /sw/lib/perl5/5.8.6/auto/Mango/forms/admin/users/update.yml
+ /sw/lib/perl5/5.8.6/auto/Mango/forms/admin/users/delete.yml
+ /sw/lib/perl5/5.8.6/auto/Mango/templates/tt/html/admin/users/create
+ /sw/lib/perl5/5.8.6/auto/Mango/templates/tt/html/admin/users/update
+ /sw/lib/perl5/5.8.6/auto/Mango/templates/tt/html/admin/users/delete
+
+From there, L</Form Mapping> automaticaly maps the form files to other base
+controllers as they're loaded. The base view class automatically appends the
+shared template paths onto the template search paths:
+
+ package MyApp::Controller::Users;
+ use base 'Mango::Catalyst::Controller::Users';
+
+ # looks for root/templates/tt/html/users/edit
+ # fallback to %SHAREDIR/templates/tt/html/users/edit
+ sub edit : Local Template('users/edit') {
+ $c->view('HTML');
+ };
+
+If you wish to provide your own templates, simply add them to your root path,
+changing the Template attribute if needed:
+
+ ## root/templates/tt/html/users/edit
+ Editting user X
+ [% form.render %]
+
+When an update to Mango is released, simply install it like any other perl dist.
+No merging. No fuss. Mango always tries to use your local files first, falling
+back to the shared files.
+
+=head2 Swappable Phat Models/Providers
+
+While it's somewhat a given that you can swap any model in catalyst out for
+another as long as the API is the same, this was a primary design goal in Mango.
+All of the models for Users, Roles, Profiles, Products, Carts and Wishlsts
+share a common API for CRUD operations and while they all default to using the
+same database, it is assumed that some people may want to get their users from
+LDAP, their users profiles from an customer existing database, and their users
+carts from the Mango database.
+
+Changing where a block of data comes from is just a matter of customizing the
+appropriate model:
+
+ package MyApp::Model::Users;
+ use base 'Mango::Catalyst::Model::Users';
+
+ sub search {
+ my ($self, $filter) = @_;
+ my $msg = $ldap->search(
+ base => "c=US",
+ filter => convert_to_ldap($filter)
+ );
+
+ return convert_to_mango_users($msg->entries);
+ };
+
+=head2 Common User API
+
+Catalyst has a wonderful Authentication plugin to handle user authentication,
+but it leaves me wanting more when it comes to working with user data that spans
+authenticated and anonymous users in a consistant manner. Mango includes its own
+Authentication plugin which exposes common user bits consistantly for
+authenticated and anonymouse users, which is pretty conveinent when people start
+extending their application.
+
+ # anonymous user
+ print $c->user->profile->name; # "Anonymous"
+ my $cart = $c->user->cart;
+ $cart->add(...);
+
+ # authenticated user
+ print $c->user->profile->name; # "Joe User"
+ my $cart = $c->user->cart;
+ $cart->add(...);
+
+The Mango authenticaton plugin also takes care of caching a users roles and
+profiles so you don't have to hit the source all of the time just to print their
+name on every page or to check role permissions. The authenticaiton plugin uses
+the various Mango models to get the job done, so feel free to drop in your own
+models to fetch user information from anywhere you need to.
+
+=head2 Better Forms
+
+I hate forms. I think working with forms is one of the rings of Hell. There are
+many forms/validation solutions on CPAN. That all have good points. That all
+have bad points. Forms are a problem to which there is no solution that works
+for everyone. So, I wrote another one for Mango. :-)
+
+It's akin to FormFu, sans the stack of templates used to render the forms bits.
+Maybe I'll migrate it later on when I get a chance.
+
+=head3 Form Configuration
+
+Mango::Form is a hybrid of C<CGI::FormBuilder> and C<FormValidator::Simple>,
+with a single config file that contains both the form definitions, the validator
+rules and the messages to output on failure:
+
+ ---
+ name: form_name
+ method: POST
+ javascript: 0
+ stylesheet: 1
+ sticky: 1
+ submit: LABEL_CREATE
+ fields:
+ - sku:
+ type: text
+ size: 25
+ maxlength: 25
+ constraints:
+ - NOT_BLANK
+ - LENGTH, 1, 25
+ - UNIQUE
+ messages:
+ NOT_BLANK: The sku field is blank.
+ - name:
+ label: MyName
+ type: text
+ size: 25
+ maxlength: 25
+ constraints:
+ - NOT_BLANK
+ - LENGTH, 1, 25
+
+=head3 Form Localization
+
+As you may have noticed in the configuration above, most of the fields have no
+messages or labels configured. By default, Mango assumes that each fields
+message is FIELDNAME_CONSTRAINTNAME and each fields label is LABEL_FIELDNAME.
+These values are sent through the localization plugin to be localized before
+being put on a page. Outside of Catalyst, this uses Mango::I18N to get the job
+done.
+
+ %Lexicon = (
+ Language => 'English',
+ LABEL_UPDATE => 'Update',
+ LABEL_SKU => 'Part Number/SKU',
+ LABEL_NAME => 'Name',
+ SKU_NOT_BLANK => 'The part number is required',
+ SKU_LENGTH => 'The part number must be between [_1] and [2] in length.',
+ };
+
+While running under Catalyst, it uses the localization plugin, which checks
+for a MyApp::I18N before falling back to using Mango::I18N.
+
+=head3 Form Mapping
+
+Mango also contains magic similiar to the FormBuilder plugin that ties these
+form configurations to specific controller actions. By default, each base
+controller has forms assigned to it by matching their action names to files in
+the shared form config directory matching the controller name.
+
+ package Mango::Catalyst::Controller::Users;
+
+ # uses %SHAREDIR/forms/users/edit.yml
+ sub edit : Local {};
+
+ # uses %SHAREDIR/forms/users/create.yml
+ sub create : Local {};
+
+These mappings can be overriden at the controller level, or even at the action
+level:
+
+ package MyApp::Controller::Users;
+ use base 'Mango::Catalyst::Controller::Users';
+ __PACKAGE__->forms_directory('/www/myapp/forms/users');
+
+ # uses /www/myapp/forms/users/edit.yml
+ sub edit : Local {};
+
+ # uses /www/myapp/forms/users/other.yml
+ sub delete : Local Form('other') {};
+
+ # uses /www/other/forms/create.yml
+ sub create : Local FormFile('/www/other/forms/create.yml') {};
+
+Within each method, one can simply call C<form>, C<submitted> and C<validate>
+to run the form validation:
+
+ sub edit : Local {
+ my $self = shift;
+ my $form = $self->form;
+
+ if {!$self->submitted) {
+ $form->values({
+ id => $user->id,
+ username => $user->username,
+ password => $user->password,
+ confirm_password => $user->password,
+ created => $user->created . '',
+ updated => $user->updated . '',
+ first_name => $profile->first_name,
+ last_name => $profile->last_name,
+ };
+ } else {$self->submitted && $self->validate) {
+ $user->password($form->field('password'));
+ $user->update;
+ };
+ };
+
+ ## user.tt
+ [% form.render %]
+
+=head2 REST-ish-able-like
+
+I'm not a true diehard REST preacher, but I do like some of the ideas and what
+the REST action controller for Catalyst has to offer. Mango makes use of the
+REST controller mostly for content-type negotiation and mapping friendly names
+to content-types using C<MIME::Types>.
+
+One of the goals was to make a Mango application available to web users and to
+remote developers as well using the REST controller.
+
+ ## serves the users info page to browsers
+ http://localhost/users/claco/
+
+ ## serves the users info to remote clients
+ my $ua = LWP::UserAgent->new;
+ $ua->header('Content-Type', 'text/x-yaml');
+ my $r = $ua->get('http://localhost/users/claco/');
+ my $user = YAML::Load($c->content);
+
+Mango adds a little bit of magic to just about everyone here. By default,
+MIME::Types doesn't have mappings for JSON or YAML. The Mango REST controller
+adds these, as well as some alternate friendly names for things, like
+.yml and .yaml => text/x-yaml. You can specify a preferred content type using
+the friendly name in the C<view> parameter:
+
+ my $ua = LWP::UserAgent->new;
+ my $r = $ua->get('http://localhost/users/claco/?view=yaml');
+ my $user = YAML::Load($c->content);
+
+in addition to the content-type parameter the REST action supplies:
+
+ my $ua = LWP::UserAgent->new;
+ my $r = $ua->get('http://localhost/users/claco/?content-type=text/x-yaml');
+ my $user = YAML::Load($c->content);
+
+The Mango REST controller also provides an alternate method to map unsupported
+methods in a browsers post to a support action in each controller:
+
+ <form method="POST" action="/users/claco/">
+ <input type="hidden" name="_method" value="DELETE" />
+ </form>
+ ...
+
+ ## called by true DELETE /users/claco/
+ sub users_DELETE : Private {};
+
+=head2 Getting Started
+
+B<Warning>: Mango is in some form of ALPHA at the moment as I'm still trying to
+find a good balance of all of the features above. The cart and admin should work.
+Still needs plenty of love and code for product/tag browsing and checkout
+workflow.
+
+Getting started with Mango couldn't be much easier. Checkout the latest source
+and install it. To start your first Mango application, simply run:
+
+ $ mango.pl MyApp
+ $ cd MyApp
+ $ script/myapp_server.pl
+
+=head1 See Also
+
+L<http://www.catalystframework.org/calendar/2006/2>,
+L<http://svn.mangoframework.com/CPAN/Mango/trunk/>
+
=head1 AUTHOR
-claco
+ Christopher H. Laco
+ claco at chrislaco.com
More information about the Catalyst-commits
mailing list