http://www.perlmonks.org?node_id=541996


in reply to Re: RFC: Class::CGI
in thread RFC: Class::CGI

I've just finished updating the code to handle all of this. Here's an example from the docs:

package My::Date::Handler; use My::Date; sub new { my ($class, $cgi) = @_; my $month = $cgi->raw_param('month'); my $day = $cgi->raw_param('day'); my $year = $cgi->raw_param('year'); return My::Date->new( month => $month, day => $day, year => $year, ); } 1;

And in the user's code:

use Class::CGI handlers => { date => 'My::Date::Handler', }; my $cgi = Class::CGI->new; my $date = $cgi->param('date'); my $day = $date->day;

It's not uploaded anywhere yet, though. I'll wait for more suggestions. I must say, it's really nice to see how clean design of classes makes extending them so easy :)

Cheers,
Ovid

New address of my CGI Course.

Replies are listed 'Best First'.
Re^3: RFC: Class::CGI
by eric256 (Parson) on Apr 08, 2006 at 04:36 UTC

    The one thing that aproach does is mean that each class is set in its parameters.. So you couldn't have two of any one type because they wouldn't know which fields to use unless you passed in the actual param that the user put. /me thinks maybe code will help here

    use Class::CGI handlers => { invoice_date => 'My::Date::Handler', sales_date => 'My::Date::Handler', }; my $cgi = Class::CGI->new; my $date = $cgi->param('invoice_date'); my $date = $cgi->param('sales_date'); my $day = $date->day;

    Sense the handler is picking the fields on its own it doesn't know which three fields belong where. Instead of having the handler pick fields maybe allow the user to specify fields to send as arguments.

    use Class::CGI handlers => { invoice_date => ['My::Date::Handler', qw(invoice_month invoice_d +ay invoice_year)], sales_date => ['My::Date::Handler', qw(sales_month sales_day sal +es_year)], }; my $cgi = Class::CGI->new; my $date = $cgi->param('invoice_date'); my $date = $cgi->param('sales_date'); my $day = $date->day;

    The main class could then grab those params and send the values to the handler so your handler would look like the following

    package My::Date::Handler; use My::Date; sub new { my ($class, $cgi, $param) = (shift,shift,shift); #standard my ($month, $day, $year) = (shift,shift,shift); #extra return My::Date->new( month => $month, day => $day, year => $year, ); } 1;

    The new method would then be sent the class, the cgi object, and the name of the handler (i.e. invoice_date, sales_date) followed by the values of any parameters listed in its definition.

    use Class::CGI handlers => { customer_id => 'My::Customer', referral_id => 'My::Customer', sales_date => ['My::Date::Handler', qw(sales_month sales_day sales_year)], }; my $cgi = Class::CGI->new; my $sales_date = $cgi->param('sales_date'); my $customer = $cgi->param('customer_id'); my $referrer = $cgi->param('referrar_id');

    I think you get the best of all worlds this way. You can have generic classes that validate the field and return it (without hardcoding the fields into the handler). You get handlers that can consume multiple fields in cases where they are known before hand (hardcoded in, like customer_id might expect some other fields in order to build the customer object), and handlers that consume multiple fields but can be passed the params they need so they are flexible. Of course maybe i'm seeing a problem where there isn't one, but date validation definitly needs to be able to be used multiple times on the same page with different fields (or sets of fields).

    The module sounds great otherwise...now if you can tie it to HTML::Template, TT and CGI::Application you will have a winner! ;)


    ___________
    Eric Hodges

      Being able to specify an arrayref so that you can pass user-defined additional parameters is a good idea anyway, but the need for it could be obviated in many cases. The following should be enough:

      use Class::CGI handlers => { invoice_date => 'My::Date::Handler', sales_date => 'My::Date::Handler', };

      This can work if you just pass the parameter name to the handler constructor. Users can then create a convention based on the name and avoid the need for configuration:

      package My::Date::Handler; use Carp; use My::Date; sub new { my $class = shift; my ( $cgi, $param_name ) = @_; $param_name =~ s/_date\z// or croak "Profile name expected to end in '_date': $param_name +"; my %date = map { $_ => scalar $cgi->raw_param( $param_name . '_' . $_ ) } qw( month day year ); return My::Date->new( %date ); } 1;

      Makeshifts last the longest.

        I'm not sure about the arrayref idea, but making the parameter name available is so obvious that I'm calling that a feature request. I'll add it.

        Cheers,
        Ovid

        New address of my CGI Course.

      Tying it into CGI::Application wouldn't be a problem. In your CGI::Application base class override cgiapp_get_query():

      package My::CGI::Application; use base 'CGI::Application'; use Class::CGI handlers => { customer_id => 'My::Customer', referral_id => 'My::Customer', sales_date => ['My::Date::Handler', qw(sales_month sales_day sales_year)], }; sub cgiapp_get_query { my $self = shift; return Class::CGI->new; } 1;