From: Chris W. <la...@us...> - 2005-03-12 21:16:53
|
Update of /cvsroot/openinteract/OpenInteract2/doc/Manual In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv14817 Modified Files: TutorialAdvanced.pod Log Message: OIN-92: finish up the rest of the declared sections Index: TutorialAdvanced.pod =================================================================== RCS file: /cvsroot/openinteract/OpenInteract2/doc/Manual/TutorialAdvanced.pod,v retrieving revision 1.6 retrieving revision 1.7 diff -C2 -d -r1.6 -r1.7 *** TutorialAdvanced.pod 4 Mar 2005 03:03:15 -0000 1.6 --- TutorialAdvanced.pod 12 Mar 2005 21:16:40 -0000 1.7 *************** *** 531,537 **** =head2 Define the class =head2 Add to declaration ! =head1 SPOPS: USING SECURITY =head1 MISC --- 531,659 ---- =head2 Define the class + SPOPS objects provide simple persistence behavior. But you may want + them to have other types of behavior as well. The recommended way of + doing this is to create your class and have it subclass the generated + SPOPS class. + + A typical use of this is to encapsulate common queries. Say you have a + 'recipe' object: + + [recipe] + class = OpenInteract2::Recipe + ... + + After using it for a while you find that you're one of your standard + queries is to find recipes with a particular ingredient posted in the + last month. It's executed from multiple actions so it makes sense to + have this query live in the same object that actually retrieves the + objects. To hold it you'd create something like this: + + package OpenInteract2::Recipe; + + use strict; + @OpenInteract2::Recipe::ISA = qw( OpenInteract2::RecipePersist ); + + sub by_ingredient_in_last_month { + my ( $class, $ingredient ) = @_; + my $where = qq{ + ingredient LIKE ? ' + AND date_part( 'epoch', CURRENT_DATETIME ) - date_part( 'epoch', posted_on ) <= 25920000 + }; + return $class->fetch_group({ + where => $where, + value => [ $ingredient ], + }); + } + + Hey, where did that C<OpenInteract2::RecipePersist> come from? + =head2 Add to declaration ! The last step is to change the name of your generated class. This is ! so people can use the name they'd expect to see ! ('OpenInteract2::Recipe' for a 'recipe' object). Changing this is simple: ! ! OLD: ! [recipe] ! class = OpenInteract2::Recipe ! ... ! ! NEW: ! [recipe] ! class = OpenInteract2::RecipePersist ! ... ! ! One other task: when we want to get the object class name from the ! context (using C<lookup_object()>) we don't want to get ! 'OpenInteract2::RecipePersist'. So we need to alias the class: ! ! [recipe] ! class = OpenInteract2::RecipePersist ! alias_class = OpenInteract2::Recipe ! ... ! ! So now when we get the class name like this we'll get the right thing: ! ! my $recipe_class = CTX->lookup_object( 'recipe' ); ! my $recent_recipes = ! $recipe_class->by_ingredient_in_last_month( 'ketchup' ); ! print "Stuff you've made recently:\n"; ! foreach my $recipe ( @{ $recent_recipes } ) { ! print " ", $recipe->name, "\n"; ! } ! ! =head2 Using security ! ! First: are you sure you need per-object security? Checking security ! can add significant overhead to object retrieval, so if your security ! requirements can be met by application security instead you should use ! it. ! ! So if you need it, adding security is as simple as setting 'is_secure' ! to 'yes' in your object configuration: ! ! [myobject] ! class = OpenInteract2::Myobject ! ... ! is_secure = yes ! ! This will add L<SPOPS::Secure> to your class's C<@ISA> and ! automatically ensure that users have READ security to retrieve an ! object and WRITE security to store or remove it. ! ! That leaves a gap: how do we know what the security should be to ! create an object? You cover this with the 'creation_security' ! configuration section. It looks like this: ! ! [myobject creation_security] ! user = WRITE ! group = site_admin_group:WRITE ! world = READ ! ! This means that we create a security object for the user who creates ! the object as WRITE, one for the 'site_admin_group' as WRITE, and one ! for the world as READ. You can skip a scope if you like -- if you only ! want users in the 'public' group to be able to see your object you'd ! use: ! ! [myobject creation_security] ! group = public_group:READ ! ! The 'site_admin_group' and 'public_group' used above is the name of ! any group found in your server configuration's 'default_objects' ! configuration section. That section typically looks like this: ! ! [default_objects] ! superuser = 1 ! supergroup = 1 ! theme = 1 ! public_group = 2 ! site_admin_group = 3 ! ! The 'groupname:PERMISSION' is a syntax enhancement: when the server ! starts up we lookup 'groupname' in 'default_objects' and substitute ! that group's ID. So with the above definitions when you create a new ! 'myobject' we'll also create a security object giving WRITE permission ! to group with ID 3. =head1 MISC |