Re: [Catalyst] Where should constraints go

2006-11-03 Thread Ian Docherty

Carl Franks wrote:


I made on very basic start [1] on being able to automatically create
constraints from the database column types. At the moment it only
supports mysql, and it's also probably very out-of-sync with the
current svn trunk - but I'd /really/ like to see it finished, and I
/really/ don't have any time to work on it, so if you want to take a
look and do something with it, that'd be great.
My primary goal was to get it working with HTML::Widget as
H-W-Constraint-DBIC [2], but there's no reason it couldn't be
integrated with any other validation package.

[1] 
http://dev.catalyst.perl.org/repos/bast/branches/DBIx-Class/columns_info_for 

[2] 
http://dev.catalystframework.org/repos/Catalyst/trunk/HTML-Widget-Constraint-DBIC/ 



Carl

Carl
Creating the constraints is not really the problem. Your approach 
certainly helps and one that any ORM should include. I can see that it 
would take a fair amount of work to cover all bases. For example, if a 
constraint was put on a DATE field such that it could not be later than 
NOW and no earlier than NOW - 20 Days. (for example).


Putting these sort of constraints is the duty of either the database 
level (where they naturally go anyway) or perhaps in the business logic 
layer.


My problem is finding a clean way of getting these constraints out of 
the Model and into the View so that I can generate meaningful error 
messages without hard-coding them in the templates. By 'clean' I mean 
not having to code the Controller to act as the middle-man and just pass 
them from the Model to the View.


Perhaps I am expecting too much.


___
List: Catalyst@lists.rawmode.org
Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.rawmode.org/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Where should constraints go

2006-11-03 Thread Carl Franks

On 03/11/06, Ian Docherty [EMAIL PROTECTED] wrote:

Carl Franks wrote:

 I made on very basic start [1] on being able to automatically create
 constraints from the database column types. At the moment it only
 supports mysql, and it's also probably very out-of-sync with the
 current svn trunk - but I'd /really/ like to see it finished, and I
 /really/ don't have any time to work on it, so if you want to take a
 look and do something with it, that'd be great.
 My primary goal was to get it working with HTML::Widget as
 H-W-Constraint-DBIC [2], but there's no reason it couldn't be
 integrated with any other validation package.

 [1]
 http://dev.catalyst.perl.org/repos/bast/branches/DBIx-Class/columns_info_for

 [2]
 
http://dev.catalystframework.org/repos/Catalyst/trunk/HTML-Widget-Constraint-DBIC/


 Carl
Carl
Creating the constraints is not really the problem. Your approach
certainly helps and one that any ORM should include. I can see that it
would take a fair amount of work to cover all bases.

Putting these sort of constraints is the duty of either the database
level (where they naturally go anyway) or perhaps in the business logic
layer.

My problem is finding a clean way of getting these constraints out of
the Model and into the View so that I can generate meaningful error
messages without hard-coding them in the templates. By 'clean' I mean
not having to code the Controller to act as the middle-man and just pass
them from the Model to the View.


The purpose of the columns_info_for branch code is to mark columns
with such flags as
'data_type', 'size', 'length_in_bytes',
or for integers... 'is_unsigned', 'range_min', 'range_max'

Then you just need to tell the validation/form package which DBIC
column corresponds to the CGI parameter, and the validation/form
package should be smart enough to check the input against the flags
set, and set an appropriate error message if it fails.

So if your 'username' column is varchar(16), DBIC would mark it
data_type = 'varchar',
size = 16,
and if the input is longer than that, then the validation package can
set the message must be no longer than 16 characters.
The HTML::Widget equivalent would be:
$w-constraint( String = 'username' );
$w-constraint( Length = 'username' )-max( 16 )-message( 'must be...' );

If your 'age' column is the mysql column unsigned tinyint, then DBIC
would mark it
data_type = 'tinyint',
is_unsigned = 1,
range_min = 0,
range_max = 256.
Again, the validation package can set appropriate error messages if
the input doesn't match those specs.
The HTML::Widget equivalent would be:
$w-constraint( Integer = 'username' )-message( 'must be an integer' );
$w-constraint( Range = 'username' )-min( 0 )-max( 256 )-message( '...' );
Which should be entirely possible to automate.


For example, if a
constraint was put on a DATE field such that it could not be later than
NOW and no earlier than NOW - 20 Days. (for example).


I don't get your example.
Is this 'constraint' something that's defined in the database as a
Stored Procedure or Function?
If so, then no, I don't see any way of automatically getting that
specification into the View, unless you use a database that lets you
use native perl-code functions, and you can use the exact same code in
the View, and you use some sort of mechanism to ensure that the
database function stays in sync with the View.

Carl

___
List: Catalyst@lists.rawmode.org
Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.rawmode.org/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Where should constraints go

2006-11-03 Thread Matt S Trout

Ian Docherty wrote:
My problem is finding a clean way of getting these constraints out of 
the Model and into the View so that I can generate meaningful error 
messages without hard-coding them in the templates. By 'clean' I mean 
not having to code the Controller to act as the middle-man and just pass 
them from the Model to the View.


Perhaps I am expecting too much.


No, I understand entirely, and you aren't expecting too much at all - except 
perhaps any expectation that this would already be fully implemented :)


We're doing this in Reaction using Moose to provide an introspectable 
metamodel so the update action class reflects its constraints off the model 
and then the form reflects its field types off the update action and the 
fields just have the constraints already there when they're doing 
validation. It's been hard work and there's a lot of hard work still to come 
but so far it works bloody well.


--
 Matt S Trout   Offering custom development, consultancy and support
  Technical Directorcontracts for Catalyst, DBIx::Class and BAST. Contact
Shadowcat Systems Ltd.  mst (at) shadowcatsystems.co.uk for more information

+ Help us build a better perl ORM: http://dbix-class.shadowcatsystems.co.uk/ +

___
List: Catalyst@lists.rawmode.org
Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.rawmode.org/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Where should constraints go

2006-11-03 Thread Rodney Broom
From: Ian Docherty [EMAIL PROTECTED]

 Putting these sort of constraints is the duty of either the database 
 level (where they naturally go anyway) or perhaps in the business logic 
 layer.

Right, constraints can come from both. I think the question is how to 
communicate those contraints up the line, ultimately to the view. Which is what 
you said below. :)


 My problem is finding a clean way of getting these constraints out of 
 the Model and into the View so that I can generate meaningful error 
 messages without hard-coding them in the templates.

I don't have the communication from layer to layer all worked out, but an 
approach I've liked is to have errors (like constraint failures) communicated 
with standard message identifiers and know data. For instance, failing length 
of 'username' could propogate a message ID of ERR_USERNAME_LENGTH, and include 
data in a list: [1, 16]. From there, the view would be able to pull messaging 
based on language or other criteria and flesh it out with the data. In TT, 
maybe something like:

[% IF field.messages %]
  [% FOR m = field.messages %]
[% sprintf( get_text(m.id), @{m.data} ) %]
  [% END %]
[% END %]

The English message for ERR_USERNAME_LENGTH might be:

  Must be between %u and %u characters



 Perhaps I am expecting too much.

I don't think so. I've seen this done pretty well, but am finding it to be a 
labor to get it all worked out under Catalyst.


btw, this general path isn't mine. I got it years ago, pre-catalyst, from 
another Cat-list person: Mark Blythe.


---
Rodney Broom


___
List: Catalyst@lists.rawmode.org
Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.rawmode.org/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Where should constraints go

2006-11-03 Thread Ian Docherty
Yes this pretty much agrees with my interpretation. It is not so much 
the location of the constraint rules as how to propagate them to the 
view (i.e the stash)


John Siracusa wrote:

Keep in mind that there are at least three possible levels of
constraints in a database-backed web app.

1. Constraints enforced by the database (e.g., maximum length for a
varchar column)

2. The constraints of your object model (e.g., alpha-numeric
characters only in usernames)

3. Application constraints (e.g., usernames that begin with acme_
may not be registered using the public web site)

That's all for one piece of information: a username.

Database constraints apply everywhere.

Object model constraints also might apply everywhere, by you may want
to bend the rules for some special cases.  (If an object model
constraint really does apply everywhere, it should probably be moved
to the database, if possible.)

Application constraints are almost certain to change (e.g., internal
admin tools usually have fewer such constraints than public end-user
tools).

If you try to smoosh up all three of these kinds of constraints into a
single definition, much pain awaits you :)  My preferred distribution
of responsibilities is:

1. Database constraints: defined in the database, and also reflected
(as much as possible) in the ORM-based classes.

2. Object model constraints: defined either in the ORM-based classes
or in classes that wrap them (if such things exist).

3. Application constraints: defined in form/field objects, which may
inspect the ORM constraints and use them as a starting point.

-John

___
List: Catalyst@lists.rawmode.org
Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
Searchable archive: 
http://www.mail-archive.com/catalyst@lists.rawmode.org/

Dev site: http://dev.catalyst.perl.org/





___
List: Catalyst@lists.rawmode.org
Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.rawmode.org/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Where should constraints go

2006-11-03 Thread John Siracusa

On 11/3/06, Ian Docherty [EMAIL PROTECTED] wrote:

Yes this pretty much agrees with my interpretation. It is not so much
the location of the constraint rules as how to propagate them to the
view (i.e the stash)


Do you mean for the purposes of client-side validation?  Or do you
just mean how to display the (server-generated) error messages in the
view?

If you mean the latter, the way I do it is to pass in a form object as
a single parameter (usually named form).  The form object itself has
a list of (possibly localized) error messages, as does each field
object contained in the form object.  All of these messages are
generated (by a $form-validate() call) before the form object is
passed to the template.

In the template, there's a place for form-wide errors to appear (if
any) plus a place near each field for field-specific errors to appear.
IMO, all required data should already exist before anything is passed
to a template.  The template should just decide where things should
go, possibly with minor massaging for visual purposes.

-John

___
List: Catalyst@lists.rawmode.org
Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.rawmode.org/
Dev site: http://dev.catalyst.perl.org/


Re: [Catalyst] Where should constraints go

2006-11-03 Thread John Siracusa

On 11/3/06, Ian Docherty [EMAIL PROTECTED] wrote:

One thing occurs to me. What I want to do is to get parameters from the
Model (or the Business layer) into the View via the stash. So for a User
object I want be able to do something like.

td align=left class=errorUsername must be between [%
schema.user.username.min %] and  [% schema.user.username.max %]
characters/td


Warning!  Localization alert! :)  Like I said before, I don't think
you really want to be passing things to the view at that granularity.
It makes for some vary hairy form templates--one for each locale, to
boot.

If you whip up all this stuff *before* passing it off to the template,
you get templates like this (shown using Mason with a
designer-friendly syntax for the form/fields which just translates
deterministically into the corresponding method calls at runtime):

   % '/messages.mc', %ARGS %

   % 'START_FORM' |fm %

   table

   tr
   td class=label% 'USERNAME:LABEL' |f %/td
   td class=field% 'USERNAME:FIELD' |f %/td
   /tr

   tr
   td class=label% 'PASSWORD:LABEL' |f %/td
   td class=field% 'PASSWORD:FIELD' |f %/td
   /tr

   tr
   td colspan=2% 'LOGIN_BUTTON:FIELD' |f %/td
   /tr

   /table

   % 'END_FORM' |fm %

That's one form template for all supported languages, complete with
extremely granular, localized error messages.  (e.g., The username
'whatever' is already taken.  Please choose another.)  The form-wide
messages go in the message box produced (or not, if no messages) at
the top by messages.mc.  The per-field errors are returned by the
USERNAME:FIELD calls and go under each field.

Even ignoring localization, you will save much sanity by constructing
all this stuff perl-side before passing it off to a template.

-John

___
List: Catalyst@lists.rawmode.org
Listinfo: http://lists.rawmode.org/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.rawmode.org/
Dev site: http://dev.catalyst.perl.org/