[Catalyst] Putting more in the View
Ian Docherty
icd at ecisecurity.com
Wed Feb 15 21:38:01 CET 2006
Hi
I have spend 5 weeks or more now on my first Catalyst application and
feel that I am coming to grips with it now and am questioning some of my
previous (bad) practices in light of what I am learning.
I note however that in all the examples of Catalyst I have seen, most of
the work takes place in the controller. The Model is pretty sparce and
there is nothing in the View (other than the Template).
This is my reasoning why this is wrong.
Take the example of a user administration set of pages. I implemented
this with the following URIs
/user/list To display a paged list of users and search facility.
/user/display/33 To display user id 33
/user/edit To create a new user (just a blank form)
/user/edit/33 To edit existing user id 33
/user/save The form submit action for a new user
/user/save/33 The form submit action for user id 33 edit
Now for the list and display functions I either pass an array of
CDBI::Users or a single CDBI::User object. The Template then extracts
the relevent fields (username, firstname, lastname date of birth etc.)
directly from the user object ('aint. TT brilliant?)
The problem is with the edit -> save workflow.
If I pass a user object to the /user/edit/33 Template it is easy enough
to pre-populate the form fields with the existing values in the same way
as I do with the /user/display/33 URI.
In the 'traditional' manner, the /user/save/33 Controller would take the
request->params and validate them. If valid the relevent user record
would be updated and that would be the end of it. If invalid however we
need to display an error message and re-populate the form with the
additions or modifications made by the user so they can correct them. In
other words sticky-forms.
This is where I have my first problem. I can't now pass the user object
back to the Template, I need to pass the request->params to the
template. I can either try to build up a CDBI::User object from the
request->params and pass that to the Template (which does not work since
CDBI cannot create a new object without writing it to the database. I
understand that DBIC can do this but I have not yet gone down this
route.). Or I can refrain from passing in a CDBI::User object to the
Template in the first place but instead pass in all the parts of the
user object separately to the stash.
I hope you are following this. Sorry for the long post but I am getting
to the important bit now...
These are the relevent bits of code.
1. Decompose a User object into separate stash variables.
2. Put the stash variables into the form (this is done with TT).
3. Do simple validation when the form is submitted, e.g. ensure that
mandatory fields are filled in.
4. Do simple manipulation of data, e.g. remove leading and trailing
whitespace, convert checkboxes into true/false values, date formats etc.
5. Do database validation. e.g. is this username already taken
6. Compose a User object from the input data from (4) if the validation
succeeds.
7. If validation fails, take the raw request->params (prior to (4)) and
re-populate the form.
In my previous experience, and in many of the examples I have seen,
steps 1,3,4,6 and 7 (and often 5 as well) takes place in the controller....
My reasoning is that 1,2,3,4 and 7 rightfully belong in the View not the
Controller. 5 and 6 should be in the Controller/Model.
To this end I have developed my Catalyst application along these lines.
I have a Myapp::V::User->objectDecompose method that takes the User
object passed to it from the URI /user/edit/33 code and puts the bits
that the view needs into the Template. (Step 1)
I have MyApp::V::User->validate which takes the request->params and
validates them (Step 3 and 4) and, on the assumption that the validation
might fail, also implements the sticky-form (Step 7).
This leaves my controller fairly clean and easier to implement with all
the messy validation and data transfer taking place in the View where in
my opinion is should be.
I welcome any comments on this approach.
Regards
Ian
More information about the Catalyst
mailing list