From: Chris W. <la...@us...> - 2005-02-26 05:04:12
|
Update of /cvsroot/openinteract/OpenInteract2/doc/Manual In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv17223 Modified Files: TutorialAdvanced.pod Log Message: OIN-92: add documentation about adding and using a lookup table and a template-only action Index: TutorialAdvanced.pod =================================================================== RCS file: /cvsroot/openinteract/OpenInteract2/doc/Manual/TutorialAdvanced.pod,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** TutorialAdvanced.pod 17 Feb 2004 04:30:11 -0000 1.4 --- TutorialAdvanced.pod 26 Feb 2005 05:04:04 -0000 1.5 *************** *** 1,2 **** --- 1,3 ---- + [%- TAGS star -%] =head1 NAME *************** *** 5,33 **** =head1 SYNOPSIS ! You are getting sleepy... ! =head1 COMMON EDITING: ADDING VALIDATION ! =head1 ADDING OBJECT BEHAVIORS ! =head2 Define the class ! =head2 Add to declaration ! =head1 ADDING SECURITY ! =head2 Secure the action ! =head2 Secure individual objects ! =head1 ADDING SPOPS BEHAVIOR ! =head1 COMMON SEARCHING: USING MULTIPLE TABLES ! =head1 SETUP LOOKUP ACTION ! =head1 SETUP TEMPLATE-ONLY ACTION ! =head1 USING MULTIPLE DATASOURCES =head1 SEE ALSO --- 6,335 ---- =head1 SYNOPSIS ! This document will walk through some of the more advanced (but still ! common) actions you can do with OpenInteract2. ! For the examples in this document we'll rely on the 'books' ! application created in L<OpenInteract2::Manual::Tutorial>. ! =head1 ACTIONS: SETTING UP A LOOKUP TABLE ! =head2 Create the data structure ! One of the immediate problems with our 'book' record is that there's ! no way to categorize them. Sure, most books are cross-category -- my ! favorite: 'Computer Programming' + 'Self-Help' -- but our books don't ! even have B<one>. ! But we don't want the user to type in any old category. We should be ! able to define a list of known categories then allow her to choose one ! of them when creating or updating a book. ! So, first we'll create a table to hold these categories. It's commonly ! known as a 'lookup' table because it's so simple, all we do is find ! values: ! CREATE TABLE book_category ( ! category_id %%INCREMENT%%, ! category varchar(25) not null, ! primary key( category_id ) ! ); ! Store this in C<struct/book_category.sql> and if you're using ! Oracle/PostgreSQL add a sequence in ! C<struct/book_category_sequence.sql>: ! CREATE SEQUENCE book_category_seq ! Now we'll need to add the table and sequence to our SQL installer ! class. In C<OpenInteract2/SQLInstall/Book.pm> change: ! my %FILES = ( ! oracle => [ 'book.sql', 'book_sequence.sql' ], ! pg => [ 'book.sql', 'book_sequence.sql' ], ! default => [ 'book.sql' ], ! ); ! to: ! ! my @tables = qw( book.sql book_category.sql ); ! my @sequences = qw( book_sequence.sql book_category_sequence.sql ); ! my %FILES = ( ! oracle => [ @tables, @sequences ], ! pg => [ @tables, @sequences ], ! default => [ @tables ], ! ); ! ! Also add an SPOPS class to C<conf/spops_book_category.ini>: ! ! [book_category] ! class = OpenInteract2::BookCategory ! isa = ! field = ! field_discover = yes ! id_field = category_id ! increment_field = yes ! sequence_name = book_category_seq ! is_secure = no ! no_insert = category_id ! no_update = category_id ! base_table = book_category ! name = category ! object_name = Book Category ! ! [book_category display] ! ACTION = lookups ! TASK = ! ! =head2 Setup lookup action ! ! And here's the interesting part -- to add simple editing functionality ! to your lookup table you can just add the following action to ! C<conf/action.ini>: ! ! [book_category] ! action_type = lookup ! object_key = book_category ! title = Book Categories ! field_list = category ! label_list = Category ! size_list = 25 ! order = category ! url_none = yes ! ! The 'action_type' setting is the important one. OI2 references a list ! of action types in the server configuration (key: ! 'action_type'). Think of these as parent actions to yours -- all they ! require is configuration and you're set. In this case you need to set: ! ! =over 4 ! ! =item B<object_key> ! ! SPOPS name of your object. ! ! =item B<title> ! ! Title of the values to edit. ! ! =item B<field_list> ! ! List of fields you want to edit. (We've only got one.) ! ! =item B<label_list> ! ! List of labels for each of the fields in C<field_list>, in the same ! order. ! ! =item B<size_list> ! ! Size of text fields to edit for each of the fields in C<field_list>, ! in the same order. ! ! =item B<order> ! ! Field/ORDER-BY clause used to retrieve the data. ! ! =back ! ! See the documentation for the C<lookup> package for more information ! and additional options you can set. ! ! Add these files to your C<MANIFEST>, modify your C<Changes> and ! C<package.conf> and update your site. You can install the SQL ! structures like this (assuming C<OPENINTERACT2> environment variable ! is set to your website): ! ! $ oi2_manage install_sql_structure --package=book \ ! --file=book_category.sql --file=book_category_sequence.sql ! ! Back in the original tuturial we ran the 'install_sql' management ! task. That's really just a wrapper around three separate tasks: ! 'install_sql_structure', 'install_sql_data' and ! 'install_sql_security'. Additionally, since we don't want to try to ! reinstall our 'book.sql' we're giving it an argument to limit the ! files it will operate on. ! ! Once you restart your server go to the 'Lookup Tables' link in your ! 'Admin Tools' box. (Or just go to the '/lookups/' URL.) You'll see ! 'Book Categories' there. Click on the link and you'll see a set of ! text entry fields, one per table row. ! ! Each entry will become a new category, so enter a few and click ! 'Save'. You'll get a status message with your entries and get taken ! back to the initial lookup tables page. Click on 'Book Categories' ! again and you'll see your categories. You can now add, edit and remove ! at will. ! ! =head2 Add field to table ! ! So now we need to add our category to the book table. Using whatever ! database tool you're comfortable with add the following definition: ! ! category_id int null ! ! When you restart the server all your 'book' objects will have the new ! property 'category_id'. Since we set 'field_discover' to 'yes' in the ! previous tutorial we didn't need to tell SPOPS or OI2 about it. ! ! But we still can't assign the category from our book editing form... ! ! =head2 Source values for field from lookup ! ! What we want to do is present a list of all the available categories ! to the user when she's editing a book. But how do we do that? ! Remember, we're using one of the Common actions and didn't actually ! write any code to do inserts and updates. ! ! Fortunately the Common actions have a callback just for this. It's ! always named "customize" -- "_display_add_customize", ! "_display_form_customize", etc. ! ! So in our action L<OpenInteract2/Action/Book.pm> we'll implement these ! callbacks. This is very similar to how we added our list of publishers ! to the search form but instead of plain strings as the source we're ! using objects: ! ! So add the following method: ! ! sub _add_categories { ! my ( $self, $template_params ) = @_; ! $template_params->{categories} = ! OpenInteract2::BookCategory->fetch_group({ order => 'category' }); ! } ! ! And reference it: ! ! sub _display_add_customize { ! my ( $self, $template_params ) = @_; ! $self->_add_categories( $template_params ); ! } ! ! sub _display_form_customize { ! my ( $self, $template_params ) = @_; ! $self->_add_categories( $template_params ); ! } ! ! Then add a reference to those categories in your data editing form: ! ! [%- count = count + 1 -%] ! [% INCLUDE label_form_select_row( label = 'Category' ! name = 'category_id', ! picked = book.category, ! list = categories, ! value_field = 'category_id', ! label_field = 'category', ! first_label = '---Categories---' ) -%] ! ! Assuming you have categrories: ! ! category_id category ! --------------------- ! 1 Self-Help ! 2 Perl ! 3 Regular Expressions ! 4 Vegetarian Cooking ! ! You'll see something like this (remember that we sorted the categories ! when we assigned them to the template parameters): ! ! <select name="category_id"> ! <option value="">---Categories---</option> ! <option value="2">Perl</option> ! <option value="3">Regular Expressions</option> ! <option value="1">Self-Help</option> ! <option value="4">Vegetarian Cooking</option> ! </select> ! ! =head2 Add fields to action configuration ! ! Finally, since we configured our SPOPS object with 'field_discover' we ! didn't have to add the field to our SPOPS configuration. But since ! common action configurations don't have this feature yet you'll have ! to add to your C<conf/action.ini> under '[book]' these keys and ! values: ! ! c_update_fields = category_id ! c_add_fields = category_id ! ! =head1 ACTIONS: A TEMPLATE CAN BE AN ACTION ! ! =head2 Another action type: template_only ! ! Another way to create an action without any code is to point it ! directly at a template. This is very useful for embeddable ! components. For instance, many actions come with a 'box' that has ! pointers to common actions. Say we wanted to create a 'Book Actions ! Box' that had links like 'Search', 'Add' and (when you're on a book ! record), 'Edit' and 'Remove'. ! ! We'll go backwards first this time, defining the action first. In your ! C<conf/action.ini> add the following: ! ! [book_box] ! action_type = template_only ! template = book::toolbox ! title = Book Tools ! url_none = yes ! ! We can now reference 'book_box' just like any other action. But first ! we need to create a simple template in C<template/toolbox.tmpl>: ! ! [%- search_url = OI.make_url( ACTION = 'book', TASK = 'search' ); ! add_url = OI.make_url( ACTION = 'book', TASK = 'display_add' ); -%] ! - <a href="[% search_url %]">Search</a> <br /> ! - <a href="[% add_url %]">Add</a> <br /> ! [% IF book -%] ! [%- edit_url = OI.make_url( ACTION = 'book', TASK = 'display_form', ! book_id = book.id ); ! remove_url = OI.make_url( ACTION = 'book', TASK = 'remove', ! book_id = book.id ) -%] ! - <a href="[% search_url %]">Edit</a> <br /> ! - <a href="[% add_url %]">Remove</a><br /> ! [% END %] ! ! We're done. Just add the new file to your C<MANIFEST> and install. ! ! You can execute the content from within a template too. For instance, ! just add the following to any template: ! ! [% OI.action_execute( 'book_box' ) %] ! ! Once it's processed you'll see your content. You do something similar ! when you place the action content in a box: ! ! [% OI.box_add( 'book_box' ) %] ! ! The 'box_add' method stores the action away for execution later (by ! another action, L<OpenInteract2::Action::Box>). But since we've ! wrapped our template as an action we can now treat it like every other ! component. ! ! It's also worth mentioning that we can still reference the template ! with Template Toolkit directives, like: ! ! [% INCLUDE book::toolbox %] ! ! The only differences are that when we call C<OI.action_execute()> we ! go through the action's security checks as well as use its cached ! content if available. The C<INCLUDE> call does not -- but it's also ! faster. ! ! =head1 ACTIONS: ADDING VALIDATION TO COMMON TASKS ! ! =head1 ACTIONS: USING MULTIPLE TABLES WITH COMMON SEARCHING ! ! =head1 ACTIONS: SECURING AN ACTION ! ! =head1 SPOPS: ADDING OBJECT BEHAVIORS ! ! =head2 Define the class ! ! =head2 Add to declaration ! ! =head1 SPOPS: USING SECURITY ! ! =head1 MISC ! ! =head2 Using Multiple Datasources =head1 SEE ALSO |