|
NAMESPOPS::Tool::DBI::MaintainLinkedList - Support objects that automatically maintain a link to the previous and next objectsSYNOPSIS$spops = { 'my' => { class => 'My::Object', isa => [ qw/ SPOPS::DBI::MySQL SPOPS::DBI / ], field => [ qw/ object_id name next_object_id previous_object_id / ], skip_undef => [ qw/ next_object_id previous_object_id / ], rules_from => [ 'SPOPS::Tool::DBI::MaintainLinkedList' ], linklist_previous => 'next_object_id', linklist_next => 'previous_object_id', ... }, }; # Create some objects; new links are maintained along the way My::Object->new({ object_id => 1, name => 'first' })->save(); My::Object->new({ object_id => 2, name => 'second' })->save(); My::Object->new({ object_id => 3, name => 'third' })->save(); my $object2 = My::Object->fetch(2); print "This object: ", $object2->name, "\n", "Previous object: ", $object2->previous_in_list->name, "\n", "Next object: ", $object2->next_in_list->name, "\n"; # This object: second # Previous object: first # Next object: third # Remove the middle object to shuffle the links $object2->remove; my $object1 = My::Object->fetch(1); print "This object: ", $object1->name, "\n", "Previous object: ", ( $object1->previous_in_list ) ? "n/a" : $object1->previous_in_list->name ), "\n", "Next object: ", $object1->next_in_list->name, "\n"; # This object: first # Previous object: n/a # Next object: third DESCRIPTIONThis package supports an SPOPS ruleset to maintain a linked list of next/previous IDs. Adding a new object will set its the 'next' link to the previous head to the new object and the 'previous' link of the new object to the previous head.ConfigurationThe following configuration entries are defined:linklist_previous ($) Name of the field that holds the ID for the previous object. linklist_next ($) Name of the field that holds the ID for the next object. linklist_head ($) Method to use for finding the head object. Options are defined below in Finding the Head. linklist_head_order ($) (optional) Used if the "linklist_head" is 'order'. The "ORDER BY" clause to use to find the head. This can be any valid SQL clause, so something like "posted_on_date DESC" would work fine. linklist_head_value ($) (optional) Used if the "linklist_head" is 'value'. Set to the value of "linklist_next" for the head object. This can be useful if your database uses 0 instead of NULL for numeric fields, or if you want to set a default for "linklist_next" to a known value rather than relying on NULL. Finding the HeadThe previous head can be found in a few ways, controlled by the configuration option 'linklist_head':null (default) Find the object with the "linklist_next" field as NULL. If you have not setup the objects properly so that there is more than one object with a NULL value you will probably get a surprise: we just take the first object returned with a NULL value in the field. value Find the object with the "linklist_next" field as "linklist_head_value". Same conditions apply for the null option. order Fetch the objects ordered by a certain field and assume the first is the head. Requires you to set "linklist_head_order" to the relevant SQL "ORDER BY" clause. METHODSpost_save_actionWhen a new object is created, it updates the "linklist_next" field of the previous object (found in the manner described above) with the ID of the object just created and the "linklist_previous" field of the saved object with the ID of the previous object. Performs no action on an update or if the option 'skip_linklist' is passed to "save()": my $object = My::Object->new({ id => 1 })->save({ skip_linklist => 1 }); The latter option can be useful if you are creating new objects which do not belong at the head of the list. (See "BUGS" for an example of how to do this.) post_remove_action Relink the previous and next objects to point to each other rather than the object just removed. BUGSNon-head insertsYou need to manually manipulate inserts not at the head of the list using something like: # do not use automatic linking for this save... my $object = My::Object->new({ id => 1 })->save({ skip_linklist => 1 }); my $field_previous = My::Object->CONFIG->{linklist_previous}; my $field_next = My::Object->CONFIG->{linklist_next}; # ...find place to insert your object (find_[previous|next]_object() # are defined by you)... my $previous = find_previous_object( ... ); my $next = find_next_object( ... ); # ...shuffle the IDs and save... $previous->{ $field_next } = $object->id; $object->{ $field_previous } = $previous->id; $object->{ $field_next } = $next->id; $next->{ $field_previous } = $object->id; eval { $previous->save(); $object->save(); $next->save(); }; TO DONone known.SEE ALSOSPOPS::Manual::ObjectRulesSPOPS::ClassFactory COPYRIGHTCopyright (c) 2001-2004 intes.net, inc.. All rights reserved.This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. AUTHORSChris Winters <chris@cwinters.com>
Visit the GSP FreeBSD Man Page Interface. |