From: <pau...@us...> - 2008-06-23 08:30:48
|
Revision: 1005 http://everydevel.svn.sourceforge.net/everydevel/?rev=1005&view=rev Author: paul_the_nomad Date: 2008-06-23 01:30:43 -0700 (Mon, 23 Jun 2008) Log Message: ----------- Methods in NodeBase.pm that govern the insertion, deletion, retrieval and counting of links. Modified Paths: -------------- trunk/ebase/TODO trunk/ebase/lib/Everything/NodeBase.pm trunk/ebase/lib/Everything/Test/NodeBase.pm Modified: trunk/ebase/TODO =================================================================== --- trunk/ebase/TODO 2008-06-22 08:21:12 UTC (rev 1004) +++ trunk/ebase/TODO 2008-06-23 08:30:43 UTC (rev 1005) @@ -42,8 +42,6 @@ ** removing sql tables from nodeballs ** allowing schemae that are optimised for each of the databases -* Add nodebase.pm methods to allow retrieval of links - * Allow retrieval of objects other than nodes from the DB e.g. links This may involve creating objects that are a superclass of nodes, Modified: trunk/ebase/lib/Everything/NodeBase.pm =================================================================== --- trunk/ebase/lib/Everything/NodeBase.pm 2008-06-22 08:21:12 UTC (rev 1004) +++ trunk/ebase/lib/Everything/NodeBase.pm 2008-06-23 08:30:43 UTC (rev 1005) @@ -766,4 +766,220 @@ } + +=head2 C<retrieve_links> + +Retrieves 'links' from the database. It takes one argument which is a +hash ref. This hash ref provides the search criteria to return +links. It may have the following keys: + +=over 4 + +=item from_node + +The node being linked from + + +=item to_node + +The node being linked to + +=item linktype + +The type of link. + +=back + +Returns an array of hash refs. + +=cut + +sub retrieve_links { + + my ( $self, $args ) = @_; + + my @column_names = keys %$args; + my $where = join ' AND ', map "$_ = ?", @column_names; + + my $cursor = $self->sqlSelectMany( "from_node, to_node, linktype, hits, food", 'links', $where, undef, [ @$args{ @column_names } ] ); + + my @results = (); + + while (my $link = $cursor->fetchrow_hashref) { + push @results, $link; + } + + return \@results; +} + + +=head2 C<retrieve_nodes_linked> + +Retrieves 'links' from the database. It takes two compulsory +arguments and a third optional one: + +=over 4 + +=item direction + +The first argument must be the word 'to' or the word 'from' indicating +whether we are searching for nodes linking to or nodes linking from. + +=item node + +This is a node being linked to or from + +=item arg_hash + +This argument is optional. It must be a hashref containing arguments +that are passed directly to C<retrieve_links>. + +=back + +Returns an array ref of node objects. + +=cut + +sub retrieve_nodes_linked { + my ( $self, $direction, $node, $args ) = @_; + + $args ||= {}; + $$args{ $direction . '_node' } = $node->get_node_id; + my $links = $self->retrieve_links( $args ); + + my @nodes = (); + my $wanted_direction = $direction eq 'to' ? 'from_node' : 'to_node'; + foreach ( @$links ) { + my $node = $self->getNode( $_->{ $wanted_direction } ); + push @nodes, $node; + } + + return \@nodes; +} + +=head2 C<total_links> + +Counts the number of 'links' in the database. It takes one argument which is a +hash ref. This hash ref provides the search criteria to return +links. It may have the following keys: + +=over 4 + +=item from_node + +The node being linked from. This may be a node object or a node id. + + +=item to_node + +The node being linked to. This may be a node object or a node id. + +=item linktype + +The type of link. + +=back + +Returns an integer. May possibly return '0 but true', so you should +use a numeric test if you want to test for the absence of links. + +=cut + +sub total_links { + my ( $self, $args ) = @_; + + foreach (qw/from_node to_node/) { + $$args{ $_ } = $$args{ $_ }->get_node_id if ref $$args{ $_ }; + } + + my @column_names = keys %$args; + my $where = join ' AND ', map "$_ = ?", @column_names; + + $self->sqlSelect( 'count(1)', 'links', $where, undef, [ @$args{ @column_names } ] ); + +} + + +=head2 C<insert_link> + +Inserts a link into the database. Takes one argument, a hash ref +whose keys are the attribute names of the new link. The keys may be: + +=over 4 + +=item from_node + +The node being linked from. This may be a node object or a node id. + + +=item to_node + +The node being linked to. This may be a node object or a node id. + +=item linktype + +The type of link. + +=back + +Returns true on success. + +=cut + +sub insert_link { + + my ( $self, $args ) = @_; + + foreach (qw/from_node to_node/) { + $$args{ $_ } = $$args{ $_ }->get_node_id if ref $$args{ $_ }; + } + + $self->sqlInsert( 'links', $args ); +} + + +=head2 C<delete_links> + +Deletes one or several links from the database. It takes one argument +which is a hash ref. This hash ref provides the search criteria +(i.e. the 'where' clause) that governs what link(s) are deleted. The +hash ref may have the following keys: + +=over 4 + +=item from_node + +The node being linked from + + +=item to_node + +The node being linked to + +=item linktype + +The type of link. + +=back + +Returns true on success. + +=cut + +sub delete_links { + + my ( $self, $args ) = @_; + + foreach (qw/from_node to_node/) { + $$args{ $_ } = $$args{ $_ }->get_node_id if ref $$args{ $_ }; + } + + my @column_names = keys %$args; + my $where = join ' AND ', map "$_ = ?", @column_names; + + $self->sqlDelete( 'links', $where, [ @$args{ @column_names } ] ); +} + + + 1; Modified: trunk/ebase/lib/Everything/Test/NodeBase.pm =================================================================== --- trunk/ebase/lib/Everything/Test/NodeBase.pm 2008-06-22 08:21:12 UTC (rev 1004) +++ trunk/ebase/lib/Everything/Test/NodeBase.pm 2008-06-23 08:30:43 UTC (rev 1005) @@ -569,4 +569,103 @@ is( join( '', @$found ), '123', '... and should return results' ); } +sub test_retrieve_links : Test(4) { + my $self = shift; + + my $inst = $self->{ nb }; + my $mock = Test::MockObject->new; + + $inst->set_always( sqlSelectMany => $mock ); + $mock->set_series( fetchrow_hashref => { qw/key1 value1 key2 value2/ }, undef ); + + my %arg_hash = (to_node => 1, from_node => 2, linktype => 3 ); + my %hash_arg = reverse %arg_hash; + + ok( my $rv = $inst->retrieve_links( \%arg_hash ), '...retrieve_links works ok'); + + my ( $method, $args ) = $inst->next_call; + is( $method, 'sqlSelectMany', '...calls DB function.' ); + my @values = @{ $$args[5] }; + my $where = join ' AND ', map "$_ = ?", @hash_arg{ @values }; + is( $$args[3], $where, '... constructs where clause.'); + is_deeply( $rv, [ { key1 => 'value1', key2 => 'value2' } ], '...returns an array ref of hash refs.'); +} + +sub test_retrieve_nodes_linked : Test( 9 ) { + + my $self = shift; + my $inst = $self->{ nb }; + $inst->set_always( retrieve_links => [ {from_node => 'from', to_node => 'to' } ] ); + + my $mock = Test::MockObject->new; + $mock->set_always( get_node_id => 999 ); + $inst->set_always( getNode => $mock ); + my $rv = $inst->retrieve_nodes_linked( 'to', $mock ); + is_deeply( $rv, [ $mock ], '...returns an array of nodes.'); + my( $method, $args ) = $inst->next_call; + is( $method, 'retrieve_links', '...calls retrieve links.'); + is_deeply( $$args[1], { to_node => 999 }, '...with to_node arg_hash.'); + ( $method, $args ) = $inst->next_call; + is( $method, 'getNode', '...retrieves nodes.'); + is( $$args[1], 'from', '...using the from_node value.'); + + $inst->retrieve_nodes_linked( 'from', $mock ); + ( $method, $args ) = $inst->next_call; + is( $method, 'retrieve_links', '...calls retrieve links.'); + is_deeply( $$args[1], { from_node => 999 }, '...with from_node arg_hash.'); + ( $method, $args ) = $inst->next_call; + is( $method, 'getNode', '...retrieves nodes.'); + is( $$args[1], 'to', '...using the to_node value.'); + +} + +sub test_total_links : Test(2) { + my $self = shift; + + my $inst = $self->{ nb }; + my $mock = Test::MockObject->new; + + $inst->set_always( sqlSelect => 2 ); + + my %arg_hash = (to_node => 1, from_node => 2, linktype => 3 ); + my %hash_arg = reverse %arg_hash; + + $inst->total_links( \%arg_hash ); + + my ( $method, $args ) = $inst->next_call; + is( $method, 'sqlSelect', '...calls DB function.' ); + my @values = @{ $$args[5] }; + my $where = join ' AND ', map "$_ = ?", @hash_arg{ @values }; + is( $$args[3], $where, '... constructs where clause.'); + +} + +sub test_delete_links : Test( 2 ) { + my $self = shift; + + my $inst = $self->{ nb }; + my $mock = Test::MockObject->new; + + $inst->set_always( sqlDelete => 2 ); + + $mock->set_series( get_node_id => 1, 2 ); + + ## setting mocks here and manipulating arg_hash to know that we + ## can pass nodes rather than just node_ids + + my %arg_hash = (to_node => $mock, from_node => $mock, linktype => 3 ); + $inst->delete_links( \%arg_hash ); + $arg_hash{to_node} = 2; + $arg_hash{from_node} = 1; + + my %hash_arg = reverse %arg_hash; + + my ( $method, $args ) = $inst->next_call; + is( $method, 'sqlDelete', '...calls DB function.' ); + my @values = @{ $$args[3] }; + my $where = join ' AND ', map "$_ = ?", @hash_arg{ @values }; + is( $$args[2], $where, '... constructs where clause.'); + +} + 1; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |