Merge 'trunk' into 'DBIx-Class-current'
Matt S Trout [Wed, 3 May 2006 14:19:00 +0000 (14:19 +0000)]
r1642@thor (orig r1505):  matthewt | 2006-04-22 16:29:28 +0000
cycle tests and a weaken call
r1657@thor (orig r1520):  bluefeet | 2006-04-26 22:15:41 +0000
Document the exitance of the DBIx::Class::ResultSource::schema() accessor.
r1660@thor (orig r1523):  matthewt | 2006-04-27 20:43:45 +0000
pod patch from ted
r1698@thor (orig r1561):  dwc | 2006-05-01 19:29:37 +0000
Add example of multi-column foreign keys
r1699@thor (orig r1562):  dwc | 2006-05-01 19:31:19 +0000
Add missing comma in example ;)

Changes
lib/DBIx/Class/Manual/Cookbook.pod
lib/DBIx/Class/Relationship/Base.pm
lib/DBIx/Class/ResultSource.pm
lib/DBIx/Class/Schema.pm
t/52cycle.t [new file with mode: 0644]

diff --git a/Changes b/Changes
index e8b7378..c7f671f 100644 (file)
--- a/Changes
+++ b/Changes
@@ -16,6 +16,9 @@ Revision history for DBIx::Class
         - CDBICompat: override find_or_create to fix column casing when
           ColumnCase is loaded
 
+0.06003
+        - added memory cycle tests and a long-needed weaken call
+
 0.06002 2006-04-20 00:42:41
         - fix set_from_related to accept undef
         - fix to Dumper-induced hash iteration bug
index 35b7d40..3518c29 100644 (file)
@@ -690,4 +690,45 @@ is enough. If the left quote differs form the right quote, the first
 notation should be used. name_sep needs to be set to allow the 
 SQL generator to put the quotes the correct place. 
 
+=head2 Overloading methods
+
+L<DBIx::Class> uses the L<Class::C3> package, which provides for redispatch of 
+method calls.  You have to use calls to C<next::method> to overload methods.  
+More information on using L<Class::C3> with L<DBIx::Class> can be found in 
+L<DBIx::Class::Manual::Component>.
+
+=head3 Changing one field whenever another changes
+
+For example, say that you have three columns, C<id>, C<number>, and 
+C<squared>.  You would like to make changes to C<number> and have
+C<squared> be automagically set to the value of C<number> squared.
+You can accomplish this by overriding C<store_column>:
+
+  sub store_column {
+    my ( $self, $name, $value ) = @_;
+    if ($name eq 'number') {
+      $self->squared($value * $value);
+    }
+    $self->next::method($name, $value);
+  }
+
+Note that the hard work is done by the call to C<next::method>, which
+redispatches your call to store_column to the superclass(es).
+
+=head3 Automatically creating related objects
+
+You might have a class C<Artist> which has many C<CD>s.  Further, you
+want to create a C<CD> object every time you insert an C<Artist> object.
+You can accomplish this by overriding C<insert>:
+
+  sub insert {
+    my ( $class, $args_ref ) = @_;
+    my $self = $class->next::method($args_ref);
+    $self->cds->new({})->fill_from_artist($self)->insert;
+    return $self;
+  }
+
+where C<fill_from_artist> is a method you specify in C<CD> which sets
+values in C<CD> based on the data in the C<Artist> object you pass in.
+
 =cut
index 2e3cd89..b193aa0 100644 (file)
@@ -29,27 +29,42 @@ methods, for predefined ones, look in L<DBIx::Class::Relationship>.
 
   __PACKAGE__->add_relationship('relname', 'Foreign::Class', $cond, $attrs);
 
-The condition needs to be an SQL::Abstract-style representation of the
-join between the tables. When resolving the condition for use in a JOIN,
-keys using the pseudo-table I<foreign> are resolved to mean "the Table on the
-other side of the relationship", and values using the pseudo-table I<self>
+The condition needs to be an L<SQL::Abstract>-style representation of the
+join between the tables. When resolving the condition for use in a C<JOIN>,
+keys using the pseudo-table C<foreign> are resolved to mean "the Table on the
+other side of the relationship", and values using the pseudo-table C<self>
 are resolved to mean "the Table this class is representing". Other
 restrictions, such as by value, sub-select and other tables, may also be
-used. Please check your database for JOIN parameter support.
+used. Please check your database for C<JOIN> parameter support.
 
-For example, if you're creating a rel from Author to Book, where the Book
-table has a column author_id containing the ID of the Author row:
+For example, if you're creating a relationship from C<Author> to C<Book>, where
+the C<Book> table has a column C<author_id> containing the ID of the C<Author>
+row:
 
   { 'foreign.author_id' => 'self.id' }
 
-will result in the JOIN clause
+will result in the C<JOIN> clause
 
-  author me JOIN book book ON bar.author_id = me.id
+  author me JOIN book book ON book.author_id = me.id
 
-You can specify as many foreign => self mappings as necessary. Each key/value
-pair provided in a hashref will be used as ANDed conditions, to add an ORed
-condition, use an arrayref of hashrefs. See the L<SQL::Abstract> documentation
-for more details.
+For multi-column foreign keys, you will need to specify a C<foreign>-to-C<self>
+mapping for each column in the key. For example, if you're creating a
+relationship from C<Book> to C<Edition>, where the C<Edition> table refers to a
+publisher and a type (e.g. "paperback"):
+
+  {
+    'foreign.publisher_id' => 'self.publisher_id',
+    'foreign.type_id'      => 'self.type_id',
+  }
+
+This will result in the C<JOIN> clause:
+
+  book me JOIN edition edition ON edition.publisher_id = me.publisher_id
+    AND edition.type_id = me.type_id
+
+Each key-value pair provided in a hashref will be used as C<AND>ed conditions.
+To add an C<OR>ed condition, use an arrayref of hashrefs. See the
+L<SQL::Abstract> documentation for more details.
 
 Valid attributes are as follows:
 
index ee55dbc..4ce8e08 100644 (file)
@@ -356,7 +356,10 @@ Returns an expression of the source to be supplied to storage to specify
 retrieval from this source. In the case of a database, the required FROM
 clause contents.
 
-=cut
+=head2 schema
+
+Returns the L<DBIx::Class::Schema> object that this result source 
+belongs too.
 
 =head2 storage
 
index ff5c868..c1ea074 100644 (file)
@@ -4,6 +4,7 @@ use strict;
 use warnings;
 
 use Carp::Clan qw/^DBIx::Class/;
+use Scalar::Util qw/weaken/;
 
 use base qw/DBIx::Class/;
 
@@ -94,6 +95,7 @@ sub register_source {
   $reg{$moniker} = $source;
   $self->source_registrations(\%reg);
   $source->schema($self);
+  weaken($source->{schema}) if ref($self);
   if ($source->result_class) {
     my %map = %{$self->class_mappings};
     $map{$source->result_class} = $moniker;
diff --git a/t/52cycle.t b/t/52cycle.t
new file mode 100644 (file)
index 0000000..0c1e330
--- /dev/null
@@ -0,0 +1,23 @@
+use strict;
+use warnings;
+use Test::More;
+
+use lib qw(t/lib);
+
+BEGIN {
+  eval { require Test::Memory::Cycle };
+  if ($@) {
+    plan skip_all => "leak test needs Test::Memory::Cycle";
+  } else {
+    plan tests => 1;
+  }
+}
+
+use DBICTest;
+use DBICTest::Schema;
+
+import Test::Memory::Cycle;
+
+my $s = DBICTest::Schema->clone;
+
+memory_cycle_ok($s, 'No cycles in schema');