Your SlideShare is downloading. ×
CGI::Prototype (NPW 2006)
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

CGI::Prototype (NPW 2006)

16,300
views

Published on

Published in: Technology

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
16,300
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Managing Complexity with CGI::Prototype brian d foy, brian@stonehenge.com Stonehenge Consulting Ser vices Nordic Perl Workshop • June 16, 2006
  • 2. Web application flow Start up Receive input Process input Return output Clean up Shut down
  • 3. Looks simple, right?
  • 4. Is the request valid? Should I process the transaction? Do I have all the necessary input? Is this part of a multi-step process? Which output do I give?
  • 5. Language agnostic
  • 6. Current fad is Model-View-Controller (MVC)
  • 7. MVC Architecture Model -> data store -> database View -> data display -> web page Controller -> user interaction -> form widgets
  • 8. Choose your poison Mason CGI::Application Maypole, Catalyst, Catalyst++ CGI::Prototype
  • 9. Using CGI::Prototype Model -> DBI, Class::DBI, XML View -> Template Toolkit, XSLT -> HTML Controller -> HTML form widgets
  • 10. Application state Each state is a namespace Each state has a Template file Change state at any time by changing namespace
  • 11. Application flow Inherit from CGI::Prototype Single URL WebApp->activate; The rest is in packages and templates CGI::Prototype handles the flow
  • 12. sub activate { my $self = shift; eval { $self->app_enter; my $this_page = $self->dispatch; $this_page->control_enter; $this_page->respond_enter; my $next_page = $this_page->respond; $this_page->respond_leave; if ($this_page ne $next_page) { $this_page->control_leave; $next_page->control_enter; } $next_page->render_enter; $next_page->render; $next_page->render_leave; $next_page->control_leave; $self->app_leave; }; $self->error($@) if $@; }
  • 13. package TPR::Dashboard::FindByName; use base qw(TPR::Dashboard); my $users = []; sub respond { my $self = shift; my $q = $self->CGI; my $name = $q->param('subscriber_name'); $users = $self->db->get_subscriber_by_name( $name ) || []; my $count = @$users; if( @$users == 1 ){ $q->param( 'subscriber_id', $users->[0]->pk ); quot;TPR::CGI::ShowSubscriberquot;; } elsif( @$users == 0 ) { quot;TPR::CGI::StartPagequot;; } else { __PACKAGE__; } } sub users { $users }
  • 14. Flexibility Change action by changing namespace CGI::Prototype object handles the input and data (Class::Prototyped) in $self Choose template with template() Template has access to self.foo
  • 15. Handling Errors Respond with Error namespace Rest of transaction does Error stuff Still has access to all data CGI::Prototype has safe mode (no 500s, hopefully)
  • 16. Multiple Responses Decide which template to use as late as possible No search results -> show search form One search result -> show details Many search results -> show list Database error -> show error page
  • 17. [% self.CGI.header %] <!DOCTYPE ...> <html> <head> <title>[% self.title %]</title> <link rel=quot;stylesheetquot; type=quot;text/cssquot; href=quot;... quot;/> </head> <body> <div id=quot;headerquot; class=quot;menubarquot;> ... </div> <div id=quot;contentquot; class=quot;middlequot;> <!-- BEGIN Content [% template %] --> [% PROCESS $template %] <!-- END Content [% template %] --> </div> <div id=quot;footerquot;> </div> </body></html>
  • 18. Add accessors... sub action { quot;add_subscriberquot; } sub title { quot;Add a subscriberquot; } my $db = TPR::Subscribers::Database::SQLite->new( $file ); sub db { $db } sub subscriber { $_[0]->db->get_subscriber_by_pk( $_[1] ); }
  • 19. ...use them in Template <title>[% self.title %]</title> [% self.CGI.start_form( Method => quot;GETquot;, Action => self.CGI.url, ) %] [% self.CGI.hidden( Name => 'action', Value => self.action, Override => 1, ) -%]
  • 20. The View just views Accessors are just accessors Do not change the state Change the state in the Controller All views then get the feature
  • 21. Change behavior __PACKAGE__->reflect->addSlots( [qw(engine FIELD autoload)] => sub { my $self = shift; require Template; Template->new( { PROCESS => [ $self->config_wrapper ], INCLUDE_PATH => quot;/web/cgi-bin/local-templatesquot;, } ); } ); sub config_wrapper { 'Wrapper.tt' } sub template { (my $package = ref $_[0] || $_[0]) =~ s/.*:://; my $file = quot;$package.ttquot;; -e quot;/web/cgi-bin/local-templates/$filequot; ? $file : quot;I could not find $package.ttquot;; }
  • 22. CGI::Prototype::Hidden is even easier
  • 23. References Introduction to CGI::Prototype http://www.ourmedia.org/node/1644 Introduction to Class::Prototyped http://www.ourmedia.org/node/1728 Various articles on stonehenge.com