[Catalyst] Setup of app with semi-parallel tables
John Napiorkowski
jjn1056 at yahoo.com
Fri Oct 13 16:12:18 CEST 2006
-- "Dr. Jennifer Nussbaum" <bg271828 at yahoo.com> wrote:
> So i have an app to port to Catalyst. Its a
> library-catalogue thing, and
> very simple--pretty much one table for a library.
>
> The catch is i have a number of them, and their all
> kinda similar but
> not exactly the same. For instance each book might
> have twenty
> fields, of which fifteen are the same (title,
> author, publisher, page
> count, purchase date, etc.) and five are different
> depending on the
> needs of that library. With this app i maintain five
> or so different
> libraries. Theres a single user table that has
> permission levels for
> each library. Also, some libraries will have certain
> needs (the "school"
> library needs a check-out system, but nothing else
> does), and there
> are some libraries that will be more complicated
> (multiple joined tables, etc.
>
> So many of the methods will be the same except for
> the slightly different
> needs of each library. So i will have
>
> http://www.mysite.com/library/jen/view/323
> http://www.mysite.com/library/work/view/98
> http://www.mysite.com/library/school/view/2923
> http://www.mysite.com/library/work/add
> http://www.mysitet.com/library/school/checkout/942
>
> etc.
>
> Whats my best overall structure for this in Cat?
> Should i use the
> Chained thing, which ive never understood? i want
> the least code
> but good flexibleness for the libraries that need
> something different.
Hi,
If most of your tables are similar that will help with
the form/template construction. If you are using
something like HTML::Widget you can create a base view
component that all the different views inherit from
that contain all the similar parts. It's good
practice to do this even if your forms are not too
similar.
Your controller methods for CRUD type operations can
also be similar. Remember, the controller is just
piping (important piping) that shouldn't care about
what rows the database model has or what fields the
query has. I use the following Chaining template for
my tables. I personally found chaining to be
something that really helped me when using catalyst.
The way I set up my system is (if the domain model and
the database are the same or nearly the same) is to
have a root chain gather all the search params and
then have create, view, edit, delete spring from that.
I doubt I'm the expert but here is how I do it. Let's
say you have a table called books that has rows you
want to view or edit.
page myapp::Controller::books;
##normal setup stuff.
sub books :Chained('/') CaptureArgs(0)
{
my $books = $c->model('db::books') ||
$c->detach('/errors/not_found');
$c->stash->{books} = $books;
}
## /books/list
sub list :Chained('books') Args(0)
{
## process any specific search params again the
## books resultset and pass it on to a template
## I process some query params for stuff like
## ?search=...&bookname=... and build something
## to pass to the books resultset.
}
## /books/create
sub create :Chained('books') Args(0)
{
## Your form handler of choice, I like the
## Formbuilder plugin but the HTML::Widget Plugin
## is also great.
}
## not an endpoint, used to get the book.
sub book :Chained('books') CaptureArgs(1)
{
my ($self, $c, $id) = @_;
## You should get the $books from the stash
## and do some sanity checks
my $books = $c->stash->{books};
my $book = $books->find({book_id=>$id}) ||
$c->detach('/errors/not_found');
$c->stash->{book} = $book;
}
## /books/[book id]/edit
sub edit :Chained('book') Args(0)
{
## edit form handler
}
## /books/[book id]/view
sub view :Chained('book') Args(0)
{
## send to the template to view the data
}
## /books/[book id]/delete
sub delete :Chained('book') Args(0)
{
## probably like
$c->stash->{book}->delete;
}
I skipped a bunch of "my ($self, $c) = @_" stuff to
make this shorter. Also, for the create, edit, delete
you want to redirect back to the list action with
something like:
$url = $c->uri_for(
$c->controller->action_for('list'),
undef,
$c->request->query_parameters,
);
If the action is processed correctly. The tutortial
CRUD example has more info on this.
$c->response->redirect( $url );
I have this in my code so much I wrote an action class
to do it for me.
Also you might want the following action to make sure
the root "/books" get redirected meaningfully:
sub index : Private
{
my ($self, $c ) = @_;
$url = $c->uri_for(
$c->controller->action_for('list'),
undef,
$c->request->query_parameters,
);
$c->response->redirect( $url );
}
You might want to see if you can get the
"Catalyst::Controller::Bindlex" package installed.
It's great because it allows you to:
## creates $c->stash->{books}
my $books :Stashed = $c->model('db::books');
and get $c->stash->{books} automatically populated.
It works very well even allows stuff like:
my @array : Stashed;
push @array, "aaa";
push @array, "bbb";
push @array, "ccc";
And you use the following to get stuff out of the
stash:
## like my $books = $c->stash->{books}
my $books :Stash;
This is a great controller but it uses some modules
that don't always compile so well. If you can get it
to work your code ends up very clean.
Like I said I am sure more experts on this list will
pick this example apart with better ways to do it.
However I find that using catalyst with Chaining,
Action Classes and a few customized controllers you
can get very clean looking code.
--john
>
> Thanks!
>
> Jen
>
>
> ---------------------------------
> Talk is cheap. Use Yahoo! Messenger to make
> PC-to-Phone calls. Great rates starting at 1¢/min.>
_______________________________________________
> List: Catalyst at lists.rawmode.org
> Listinfo:
> http://lists.rawmode.org/mailman/listinfo/catalyst
> Searchable archive:
>
http://www.mail-archive.com/[email protected]/
> Dev site: http://dev.catalyst.perl.org/
>
__________________________________________________
Do You Yahoo!?
Tired of spam? Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
More information about the Catalyst
mailing list