From d94f7e813dcc0fa5de6d46a0c9739fdba22b44cf Mon Sep 17 00:00:00 2001 From: Alexander Hartmaier Date: Sat, 23 Oct 2010 13:34:31 +0200 Subject: [PATCH] documentation fixes and improvements --- Changes | 1 + lib/DBIx/Class/ResultSet/RecursiveUpdate.pm | 170 +++++++++++++++----- 2 files changed, 134 insertions(+), 37 deletions(-) diff --git a/Changes b/Changes index 3de0d2c..7103991 100644 --- a/Changes +++ b/Changes @@ -3,6 +3,7 @@ Revision history for DBIx::Class::ResultSet::RecursiveUpdate {{ $NEXT }} - Warn instead of throwing an exception if a key is neither a column, a relationship nor a many-to-many helper. + - More documentation improvements 0.20 2010-10-19 09:25:33 Europe/Vienna - Support has_many relationships with multi-column primary keys diff --git a/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm b/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm index cdfd1ff..2d0c235 100644 --- a/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm +++ b/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm @@ -575,6 +575,9 @@ __END__ unknown_params_ok => 1, }); + # You'll get a warning if you pass non-result specific data to + # recursive_update. See L + # for more information how to prevent this. =head1 DESCRIPTION @@ -582,28 +585,27 @@ This is still experimental. You can feed the ->create method of DBIx::Class with a recursive datastructure and have the related records created. Unfortunately you cannot do a similar -thing with update_or_create. -This module tries to fill that void until L has an api itself. +thing with update_or_create. This module tries to fill that void until +L has an api itself. The functional interface can be used without modifications of the model, for example by form processors like L. -It is a base class for Ls providing the method recursive_update -which works just like update_or_create but can recursively update or create -data objects composed of multiple rows. All rows need to be identified by primary keys -- so you need to provide them in the update structure (unless they can be deduced from -the parent row - for example when you have a belongs_to relationship). -If not all columns comprising the primary key are specified a new row will be created, -with the expectation that the missing columns will be filled by it (as in the case of auto_increment -primary keys). +It is a base class for Ls providing the method +recursive_update which works just like update_or_create but can recursively +update or create result objects composed of multiple rows. All rows need to be +identified by primary keys so you need to provide them in the update structure +(unless they can be deduced from the parent row. For example a related row of +a belongs_to relationship). If any of the primary key columns are missing, +a new row will be created, with the expectation that the missing columns will +be filled by it (as in the case of auto_increment primary keys). - -If the resultset itself stores an assignement for the primary key, +If the resultset itself stores an assignment for the primary key, like in the case of: my $restricted_rs = $user_rs->search( { id => 1 } ); -then you need to inform recursive_update about the additional predicate with the fixed_fields attribute: +you need to inform recursive_update about the additional predicate with the fixed_fields attribute: my $user = $restricted_rs->recursive_update( { owned_dvds => [ @@ -619,11 +621,30 @@ then you need to inform recursive_update about the additional predicate with the For a many_to_many (pseudo) relation you can supply a list of primary keys from the other table and it will link the record at hand to those and -only those records identified by them. This is convenient for handling web +only those records identified by them. This is convenient for handling web forms with check boxes (or a select field with multiple choice) that lets you update such (pseudo) relations. -For a description how to set up base classes for ResultSets see L. +For a description how to set up base classes for ResultSets see +L. + +=head2 Additional data in the updates hashref + +If you pass additional data to recursive_update which doesn't match a column +name, column accessor, relationship or many-to-many helper accessor, it will +throw a warning by default. To disable this behaviour you can set the +unknown_params_ok attribute to a true value. + +The warning thrown is: +"No such column, relationship, many-to-many helper accessor or generic accessor '$key'" + +When used by L this can happen if you have +additional form fields that aren't relevant to the database but don't have the +noupdate attribute set to a true value. + +NOTE: in a future version this behaviour will change and throw an exception +instead of a warning! + =head1 DESIGN CHOICES @@ -694,6 +715,67 @@ In this case recursive_update defaults to nullifying the foreign columns. In this case recursive_update deletes the foreign rows. +Updating the relationship: + + Passing ids: + + my $user = $user_rs->recursive_update( { + id => 1, + owned_dvds => [1, 2], + }); + + Passing hashrefs: + + my $user = $user_rs->recursive_update( { + id => 1, + owned_dvds => [ + { + name => 'temp name 1', + }, + { + name => 'temp name 2', + }, + ], + }); + + Passing objects: + + my $user = $user_rs->recursive_update( { + id => 1, + owned_dvds => [ $dvd1, $dvd2 ], + }); + + You can even mix them: + + my $user = $user_rs->recursive_update( { + id => 1, + owned_dvds => [ 1, { id => 2 } ], + }); + +Clearing the relationship: + + my $user = $user_rs->recursive_update( { + id => 1, + owned_dvds => undef, + }); + + This is the same as passing an empty array: + + my $user = $user_rs->recursive_update( { + id => 1, + owned_dvds => [], + }); + +=head2 Treatment of many-to-many pseudo relations + +If a many-to-many accessor key is included in the data structure with a value +of undef or an empty array, all existing related rows are unlinked. + +When the array contains elements they are updated if they exist, created when +not and deleted if not included. + +See L for many-to-many pseudo relationship detection. + Updating the relationship: Passing ids: @@ -721,13 +803,16 @@ Updating the relationship: Passing objects: - TODO + my $dvd = $dvd_rs->recursive_update( { + id => 1, + tags => [ $tag1, $tag2 ], + }); You can even mix them: my $dvd = $dvd_rs->recursive_update( { id => 1, - tags => [ '2', { id => '3' } ], + tags => [ 2, { id => 3 } ], }); Clearing the relationship: @@ -744,20 +829,6 @@ Clearing the relationship: tags => [], }); -=head2 Treatment of many-to-many pseudo relations - -The function gets the information about m2m relations from L. -If it isn't loaded in the ResultSource classes the code relies on the fact that: - - if($object->can($name) and - !$object->result_source->has_relationship($name) and - $object->can( 'set_' . $name ) - ) - -Then $name must be a many to many pseudo relation. -And that in a similarly ugly was I find out what is the ResultSource of -objects from that many to many pseudo relation. - =head1 INTERFACE @@ -769,17 +840,39 @@ The method that does the work here. =head2 is_m2m -$self->is_m2m( 'name ' ) - answers the question if 'name' is a many to many -(pseudo) relation on $self. +=over 4 + +=item Arguments: $name + +=item Return Value: true, if $name is a many to many pseudo-relationship + +=back + +The function gets the information about m2m relations from +L. If it isn't loaded in the ResultSource +class, the code relies on the fact: + + if($object->can($name) and + !$object->result_source->has_relationship($name) and + $object->can( 'set_' . $name ) + ) + +to identify a many to many pseudo relationship. In a similar ugly way the +ResultSource of that many to many pseudo relationship is detected. + +So if you need many to many pseudo relationship support, it's strongly +recommended to load L in your ResultSource +class! =head2 get_m2m_source -$self->get_m2m_source( 'name' ) - returns the ResultSource linked to by the many -to many (pseudo) relation 'name' from $self. +=over 4 +=item Arguments: $name -=head1 DIAGNOSTICS +=item Return Value: $result_source +=back =head1 CONFIGURATION AND ENVIRONMENT @@ -789,6 +882,9 @@ DBIx::Class::RecursiveUpdate requires no configuration files or environment vari DBIx::Class +optional but recommended: + DBIx::Class::IntrospectableM2M + =head1 INCOMPATIBILITIES None reported. @@ -796,7 +892,7 @@ None reported. =head1 BUGS AND LIMITATIONS -No bugs have been reported. +The list of reported bugs can be viewed at L. Please report any bugs or feature requests to C, or through the web interface at -- 2.45.2