Moved might_have compat back out into a CDBICompat class and documented stuff
Matt S Trout [Sun, 18 Sep 2005 17:58:03 +0000 (17:58 +0000)]
lib/DBIx/Class.pm
lib/DBIx/Class/CDBICompat.pm
lib/DBIx/Class/CDBICompat/MightHave.pm [new file with mode: 0644]
lib/DBIx/Class/DB.pm
lib/DBIx/Class/Relationship.pm
lib/DBIx/Class/Relationship/Base.pm
lib/DBIx/Class/Relationship/BelongsTo.pm
lib/DBIx/Class/Relationship/CascadeActions.pm
lib/DBIx/Class/Relationship/HasOne.pm
t/lib/DBICTest/Schema/HelperRels.pm

index 83064ce..db6eda0 100644 (file)
@@ -61,7 +61,7 @@ yo load the approriate PK::Auto subclass - e.g.
 interface)
 
 If you fancy playing around with DBIx::Class from scratch, then read the docs
-for ::Table and ::Relationship,
+for DBIx::Class::Table, ::Row, ::Schema, ::DB and ::Relationship,
 
   use base qw/DBIx::Class/;
   __PACKAGE__->load_components(qw/Core DB/);
index daf5822..88c0818 100644 (file)
@@ -18,6 +18,7 @@ __PACKAGE__->load_own_components(qw/
   ColumnCase
   HasMany
   HasA
+  MightHave
   LazyLoading
   AutoUpdate
   TempColumns
diff --git a/lib/DBIx/Class/CDBICompat/MightHave.pm b/lib/DBIx/Class/CDBICompat/MightHave.pm
new file mode 100644 (file)
index 0000000..e661f6b
--- /dev/null
@@ -0,0 +1,16 @@
+package DBIx::Class::CDBICompat::MightHave;
+
+use strict;
+use warnings;
+
+sub might_have {
+  my ($class, $rel, $f_class, @columns) = @_;
+  if (ref $columns[0] || !defined $columns[0]) {
+    return $class->NEXT::might_have($rel, $f_class, @columns);
+  } else {
+    return $class->NEXT::might_have($rel, $f_class, undef,
+                                     { proxy => \@columns });
+  }
+}
+
+1;
index 905b908..a758b8f 100644 (file)
@@ -14,13 +14,14 @@ DBIx::Class::DB - Simple DBIx::Class Database connection by class inheritance
   package MyDB;
 
   use base qw/DBIx::Class/;
-  __PACKAGE__->load_components('Core');
+  __PACKAGE__->load_components('DB');
 
   __PACKAGE__->connection('dbi:...', 'user', 'pass', \%attrs);
 
   package MyDB::MyTable;
 
   use base qw/MyDB/;
+  __PACKAGE__->load_components('Core');
 
   ...
 
index d7d1675..dce0036 100644 (file)
@@ -29,10 +29,53 @@ This class handles relationships between the tables in your database
 model. It allows your to set up relationships, and to perform joins
 on searches.
 
+This POD details only the convenience methods for setting up standard
+relationship types. For more information see ::Relationship::Base
+
 =head1 METHODS
 
+All convenience methods take a signature of the following format -
+
+  __PACKAGE__>method_name('relname', 'Foreign::Class', $join?, $attrs?);
+
+
+
 =over 4
 
+=item has_one
+
+  my $f_obj = $obj->relname;
+
+Creates a one-one relationship with another class; defaults to PK-PK for
+the join condition unless a condition is specified.
+
+=item might_have
+
+  my $f_obj = $obj->relname;
+
+Creates an optional one-one relationship with another class; defaults to PK-PK
+for the join condition unless a condition is specified.
+
+=item has_many
+
+  my @f_obj = $obj->relname($cond?, $attrs?);
+  my $f_result_set = $obj->relname($cond?, $attrs?);
+
+  $obj->add_to_relname(\%col_data);
+
+Creates a one-many relationship with another class; 
+
+=item belongs_to
+
+  my $f_obj = $obj->relname;
+
+  $obj->relname($new_f_obj);
+
+Creates a relationship where we store the foreign class' PK; if $join is a
+column name instead of a condition that is assumed to be the FK, if not
+has_many assumes the FK is the relname is that is a column on the current
+class.
+
 =cut
 
 1;
index 0b12a3b..c7fa861 100644 (file)
@@ -23,6 +23,19 @@ on searches.
 
 =over 4
 
+=item add_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 - for example if you're creating a rel from Foo to Bar
+
+  { 'foreign.foo_id' => 'self.id' }
+
+will result in a JOIN clause like
+
+  foo me JOIN bar bar ON bar.foo_id = me.id
+
 =cut
 
 sub add_relationship {
@@ -140,11 +153,23 @@ sub _cond_value {
   return $self->NEXT::ACTUAL::_cond_value($attrs, $key, $value)
 }
 
+=item search_related
+
+  My::Table->search_related('relname', $cond, $attrs);
+
+=cut
+
 sub search_related {
   my $self = shift;
   return $self->_query_related('search', @_);
 }
 
+=item count_related
+
+  My::Table->count_related('relname', $cond, $attrs);
+
+=cut
+
 sub count_related {
   my $self = shift;
   return $self->_query_related('count', @_);
@@ -176,11 +201,23 @@ sub _query_related {
            )->$meth($query, $attrs);
 }
 
+=item create_related
+
+  My::Table->create_related('relname', \%col_data);
+
+=cut
+
 sub create_related {
   my $class = shift;
   return $class->new_related(@_)->insert;
 }
 
+=item new_related
+
+  My::Table->new_related('relname', \%col_data);
+
+=cut
+
 sub new_related {
   my ($self, $rel, $values, $attrs) = @_;
   $self->throw( "Can't call new_related as class method" ) 
@@ -199,6 +236,12 @@ sub new_related {
   return $self->resolve_class($rel_obj->{class})->new(\%fields);
 }
 
+=item find_related
+
+  My::Table->find_related('relname', @pri_vals | \%pri_vals);
+
+=cut
+
 sub find_related {
   my $self = shift;
   my $rel = shift;
@@ -215,11 +258,23 @@ sub find_related {
   return $self->resolve_class($rel_obj->{class})->find($query);
 }
 
+=item find_or_create_related
+
+  My::Table->find_or_create_related('relname', \%col_data);
+
+=cut
+
 sub find_or_create_related {
   my $self = shift;
   return $self->find_related(@_) || $self->create_related(@_);
 }
 
+=item set_from_related
+
+  My::Table->set_from_related('relname', $rel_obj);
+
+=cut
+
 sub set_from_related {
   my ($self, $rel, $f_obj) = @_;
   my $rel_obj = $self->_relationships->{$rel};
@@ -243,12 +298,24 @@ sub set_from_related {
   return 1;
 }
 
+=item update_from_related
+
+  My::Table->update_from_related('relname', $rel_obj);
+
+=cut
+
 sub update_from_related {
   my $self = shift;
   $self->set_from_related(@_);
   $self->update;
 }
 
+=item delete_related
+
+  My::Table->delete_related('relname', $cond, $attrs);
+
+=cut
+
 sub delete_related {
   my $self = shift;
   return $self->search_related(@_)->delete;
index 4acb8fe..cda5fb8 100644 (file)
@@ -39,4 +39,12 @@ sub belongs_to {
   return 1;
 }
 
+=head1 AUTHORS
+
+Alexander Hartmaier <Alexander.Hartmaier@t-systems.at>
+
+Matt S. Trout <mst@shadowcatsystems.co.uk>
+
+=cut
+
 1;
index 53f15b0..b26345b 100644 (file)
@@ -12,7 +12,7 @@ sub delete {
   my %rels = %{ $self->_relationships };
   my @cascade = grep { $rels{$_}{attrs}{cascade_delete} } keys %rels;
   foreach my $rel (@cascade) {
-    $_->delete for $self->search_related($rel);
+    $self->search_related($rel)->delete;
   }
   return $ret;
 }
index ea97e7d..9f821a4 100644 (file)
@@ -12,11 +12,8 @@ sub has_one {
 }
 
 sub _has_one {
-  my ($class, $join_type, $rel, $f_class, @columns) = @_;
-  my $cond;
-  if (ref $columns[0]) {
-    $cond = shift @columns;
-  } else {
+  my ($class, $join_type, $rel, $f_class, $cond, $attrs) = @_;
+  unless ($cond) {
     my ($pri, $too_many) = keys %{ $class->_primaries };
     $class->throw( "might_have/has_one can only infer join for a single primary key; ${class} has more" )
       if $too_many;
@@ -28,20 +25,14 @@ sub _has_one {
       $class->throw( "might_have/has_one can only infer join for a single primary key; ${f_class} has more" )
         if $too_many;
     }
-    $cond = { "foreign.${f_key}" => "self.${pri}" },
+    $cond = { "foreign.${f_key}" => "self.${pri}" };
   }
-  shift(@columns) unless defined $columns[0]; # Explicit empty condition
-  my %attrs;
-  if (ref $columns[0] eq 'HASH') {
-    %attrs = %{shift @columns};
-  }
-  shift(@columns) unless defined $columns[0]; # Explicit empty attrs
   $class->add_relationship($rel, $f_class,
    $cond,
-   { accessor => 'single', (@columns ? (proxy => \@columns) : ()),
+   { accessor => 'single',
      cascade_update => 1, cascade_delete => 1,
      ($join_type ? ('join_type' => $join_type) : ()),
-     %attrs });
+     %{$attrs || {}} });
   1;
 }
 
index 590c99f..bd74259 100644 (file)
@@ -12,7 +12,8 @@ DBICTest::Schema::CD->belongs_to('artist', 'DBICTest::Schema::Artist');
 DBICTest::Schema::CD->has_many(tracks => 'DBICTest::Schema::Track');
 DBICTest::Schema::CD->has_many(tags => 'DBICTest::Schema::Tag');
 
-DBICTest::Schema::CD->might_have(liner_notes => 'DBICTest::Schema::LinerNotes' => qw/notes/);
+DBICTest::Schema::CD->might_have(liner_notes => 'DBICTest::Schema::LinerNotes',
+                                  undef, { proxy => [ qw/notes/ ] });
 
 DBICTest::Schema::SelfRefAlias->belongs_to(
   self_ref => 'DBICTest::Schema::SelfRef');