From: Matt S Trout Date: Sat, 23 Jul 2005 05:04:01 +0000 (+0000) Subject: Now passing four more tests, has_a and has_many compliance extended X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=9bc6db133eae500322e0e3670d5509d27d208f9e;hp=b8e1e21f0fcd55e6e3ce987e57601b279a75b666;p=dbsrgits%2FDBIx-Class-Historic.git Now passing four more tests, has_a and has_many compliance extended --- diff --git a/lib/DBIx/Class/CDBICompat/AccessorMapping.pm b/lib/DBIx/Class/CDBICompat/AccessorMapping.pm index 07e72ac..1604a7c 100644 --- a/lib/DBIx/Class/CDBICompat/AccessorMapping.pm +++ b/lib/DBIx/Class/CDBICompat/AccessorMapping.pm @@ -8,7 +8,7 @@ use NEXT; sub mk_group_accessors { my ($class, $group, @cols) = @_; unless ($class->can('accessor_name') || $class->can('mutator_name')) { - return $class->NEXT::mk_group_accessors($group => @cols); + return $class->NEXT::ACTUAL::mk_group_accessors($group => @cols); } foreach my $col (@cols) { my $ro_meth = ($class->can('accessor_name') @@ -18,7 +18,7 @@ sub mk_group_accessors { ? $class->mutator_name($col) : $col); if ($ro_meth eq $wo_meth) { - $class->mk_group_accessors($group => [ $ro_meth => $col ]); + $class->NEXT::ACTUAL::mk_group_accessors($group => [ $ro_meth => $col ]); } else { $class->mk_group_ro_accessors($group => [ $ro_meth => $col ]); $class->mk_group_wo_accessors($group => [ $wo_meth => $col ]); @@ -26,4 +26,23 @@ sub mk_group_accessors { } } +sub create { + my ($class, $attrs, @rest) = @_; + die "create needs a hashref" unless ref $attrs eq 'HASH'; + $attrs = { %$attrs }; + my %att; + foreach my $col (keys %{ $class->_columns }) { + if ($class->can('accessor_name')) { + my $acc = $class->accessor_name($col); +#warn "$col $acc"; + $att{$col} = delete $attrs->{$acc} if exists $attrs->{$acc}; + } + if ($class->can('mutator_name')) { + my $mut = $class->mutator_name($col); + $att{$col} = delete $attrs->{$mut} if exists $attrs->{$mut}; + } + } + return $class->NEXT::ACTUAL::create({ %$attrs, %att }, @rest); +} + 1; diff --git a/lib/DBIx/Class/CDBICompat/HasA.pm b/lib/DBIx/Class/CDBICompat/HasA.pm index e5c2cf0..b90d11c 100644 --- a/lib/DBIx/Class/CDBICompat/HasA.pm +++ b/lib/DBIx/Class/CDBICompat/HasA.pm @@ -43,12 +43,16 @@ sub set_has_a { sub store_has_a { my ($self, $rel, $obj) = @_; - return $self->set_column($rel, $obj) unless ref $obj; + unless (ref $obj) { + delete $self->{_relationship_data}{$rel}; + return $self->store_column($rel, $obj); + } my $rel_obj = $self->_relationships->{$rel}; die "Can't set $rel: object $obj is not of class ".$rel_obj->{class} unless $obj->isa($rel_obj->{class}); $self->{_relationship_data}{$rel} = $obj; - $self->set_column($rel, ($obj->_ident_values)[0]); + #warn "Storing $obj: ".($obj->_ident_values)[0]; + $self->store_column($rel, ($obj->_ident_values)[0]); return $obj; } diff --git a/lib/DBIx/Class/CDBICompat/HasMany.pm b/lib/DBIx/Class/CDBICompat/HasMany.pm index ad1cf66..7c5349c 100644 --- a/lib/DBIx/Class/CDBICompat/HasMany.pm +++ b/lib/DBIx/Class/CDBICompat/HasMany.pm @@ -12,9 +12,15 @@ sub has_many { if $too_many; if (ref $f_key eq 'HASH') { $args = $f_key; undef $f_key; }; unless ($f_key) { - ($f_key) = grep { $f_class && $_->{class} eq $class } + ($f_key) = grep { $_->{class} && $_->{class} eq $class } $f_class->_relationships; } + unless ($f_key) { + #warn join(', ', %{ $f_class->_columns }); + $class =~ /([^\:]+)$/; + #warn $1; + $f_key = lc $1 if $f_class->_columns->{lc $1}; + } die "Unable to resolve foreign key for has_many from ${class} to ${f_class}" unless $f_key; die "No such column ${f_key} on foreign class ${f_class}" diff --git a/lib/DBIx/Class/SQL.pm b/lib/DBIx/Class/SQL.pm index 53b7692..a06062e 100644 --- a/lib/DBIx/Class/SQL.pm +++ b/lib/DBIx/Class/SQL.pm @@ -26,6 +26,7 @@ __PACKAGE__->mk_classdata('_sql_statements', sub _get_sql { my ($class, $name, $cols, $from, $cond) = @_; my $sql = $class->_sql_statements->{$name}->($cols, $from, $cond); + #warn $sql; return $sql; } diff --git a/lib/DBIx/Class/Table.pm b/lib/DBIx/Class/Table.pm index 78a97bd..56eea71 100644 --- a/lib/DBIx/Class/Table.pm +++ b/lib/DBIx/Class/Table.pm @@ -9,6 +9,8 @@ __PACKAGE__->mk_classdata('_columns' => {}); __PACKAGE__->mk_classdata('_table_name'); +__PACKAGE__->mk_classdata('table_alias'); # FIXME XXX + sub new { my ($class, $attrs) = @_; $class = ref $class if ref $class; diff --git a/t/cdbi-t/01-columns.t b/t/cdbi-t/01-columns.t index 2c5fa2e..0841e1e 100644 --- a/t/cdbi-t/01-columns.t +++ b/t/cdbi-t/01-columns.t @@ -95,12 +95,12 @@ ok(!State->find_column('HGLAGAGlAG'), '!find_column HGLAGAGlAG'); my @grps = sort State->__grouper->groups_for(State->_find_columns(qw/rain capital/)); is @grps, 2, "Rain and Capital = 2 groups"; - @grps = sort @grps; # Because DBIx::Class is hash-based + @grps = sort @grps; # Because the underlying API is hash-based is $grps[0], 'Other', " - Other"; is $grps[1], 'Weather', " - Weather"; } -SKIP: { +{ local $SIG{__WARN__} = sub { }; eval { DBIx::Class->retrieve(1) }; like $@, qr/Can't retrieve unless primary columns are defined/, "Need primary key for retrieve"; diff --git a/t/cdbi-t/02-Film.t b/t/cdbi-t/02-Film.t index 68ee88d..3a27e78 100644 --- a/t/cdbi-t/02-Film.t +++ b/t/cdbi-t/02-Film.t @@ -174,7 +174,7 @@ eval { cmp_ok(Film->search(Director => 'Elaine May'), '==', 0, "0 Films by Elaine May"); SKIP: { - skip "No deprecated warnings from DBIx::Class", 1; + skip "No deprecated warnings from compat layer", 1; is $deprecated, 1, "Got a deprecated warning"; } } diff --git a/t/cdbi-t/12-filter.t b/t/cdbi-t/12-filter.t new file mode 100644 index 0000000..a51d34d --- /dev/null +++ b/t/cdbi-t/12-filter.t @@ -0,0 +1,169 @@ +use strict; +use Test::More; + +BEGIN { + eval "use DBD::SQLite"; + plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 50); +} + +use lib 't/testlib'; +use Actor; +use Film; +Film->has_many(actors => 'Actor'); +Actor->has_a('film' => 'Film'); +Actor->add_constructor(double_search => 'name = ? AND salary = ?'); + +my $film = Film->create({ Title => 'MY Film' }); +my $film2 = Film->create({ Title => 'Another Film' }); + +my @act = ( + Actor->create( + { + name => 'Actor 1', + film => $film, + salary => 10, + } + ), + Actor->create( + { + name => 'Actor 2', + film => $film, + salary => 20, + } + ), + Actor->create( + { + name => 'Actor 3', + film => $film, + salary => 30, + } + ), + Actor->create( + { + name => 'Actor 4', + film => $film2, + salary => 50, + } + ), +); + +eval { + my @actors = $film->actors(name => 'Actor 1'); + is @actors, 1, "Got one actor from restricted has_many"; + is $actors[0]->name, "Actor 1", "Correct name"; +}; +is $@, '', "No errors"; + +{ + my @actors = Actor->double_search("Actor 1", 10); + is @actors, 1, "Got one actor"; + is $actors[0]->name, "Actor 1", "Correct name"; +} + +{ + ok my @actors = Actor->salary_between(0, 100), "Range 0 - 100"; + is @actors, 4, "Got all"; +} + +{ + my @actors = Actor->salary_between(100, 200); + is @actors, 0, "None in Range 100 - 200"; +} + +{ + ok my @actors = Actor->salary_between(0, 10), "Range 0 - 10"; + is @actors, 1, "Got 1"; + is $actors[0]->name, $act[0]->name, "Actor 1"; +} + +{ + ok my @actors = Actor->salary_between(20, 30), "Range 20 - 20"; + @actors = sort { $a->salary <=> $b->salary } @actors; + is @actors, 2, "Got 2"; + is $actors[0]->name, $act[1]->name, "Actor 2"; + is $actors[1]->name, $act[2]->name, "and Actor 3"; +} + +{ + ok my @actors = Actor->search(Film => $film), "Search by object"; + is @actors, 3, "3 actors in film 1"; +} + +#---------------------------------------------------------------------- +# Iterators +#---------------------------------------------------------------------- + +SKIP: { + skip "Compat layer doesn't have iterator support yet", 33; + +sub test_normal_iterator { + my $it = $film->actors; + isa_ok $it, "Class::DBI::Iterator"; + is $it->count, 3, " - with 3 elements"; + my $i = 0; + while (my $film = $it->next) { + is $film->name, $act[ $i++ ]->name, "Get $i"; + } + ok !$it->next, "No more"; + is $it->first->name, $act[0]->name, "Get first"; +} + +test_normal_iterator; +{ + Film->has_many(actor_ids => [ Actor => 'id' ]); + my $it = $film->actor_ids; + isa_ok $it, "Class::DBI::Iterator"; + is $it->count, 3, " - with 3 elements"; + my $i = 0; + while (my $film_id = $it->next) { + is $film_id, $act[ $i++ ]->id, "Get id $i"; + } + ok !$it->next, "No more"; + is $it->first, $act[0]->id, "Get first"; +} + +# make sure nothing gets clobbered; +test_normal_iterator; + +{ + my @acts = $film->actors->slice(1, 2); + is @acts, 2, "Slice gives 2 actor"; + is $acts[0]->name, "Actor 2", "Actor 2"; + is $acts[1]->name, "Actor 3", "and actor 3"; +} + +{ + my @acts = $film->actors->slice(1); + is @acts, 1, "Slice of 1 actor"; + is $acts[0]->name, "Actor 2", "Actor 2"; +} + +{ + my @acts = $film->actors->slice(2, 8); + is @acts, 1, "Slice off the end"; + is $acts[0]->name, "Actor 3", "Gets last actor only"; +} + +package Class::DBI::My::Iterator; + +use base 'Class::DBI::Iterator'; + +sub slice { qw/fred barney/ } + +package main; + +Actor->iterator_class('Class::DBI::My::Iterator'); + +{ + my @acts = $film->actors->slice(1, 2); + is @acts, 2, "Slice gives 2 results"; + ok eq_set(\@acts, [qw/fred barney/]), "Fred and Barney"; + + ok $film->actors->delete_all, "Can delete via iterator"; + is $film->actors, 0, "no actors left"; + + eval { $film->actors->delete_all }; + is $@, '', "Deleting again does no harm"; +} + +} # end SKIP block diff --git a/t/cdbi-t/15-accessor.t b/t/cdbi-t/15-accessor.t new file mode 100644 index 0000000..35cf44d --- /dev/null +++ b/t/cdbi-t/15-accessor.t @@ -0,0 +1,195 @@ +use strict; +use Test::More; + +BEGIN { + eval "use DBD::SQLite"; + plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 55); +} + +INIT { + #local $SIG{__WARN__} = + #sub { like $_[0], qr/clashes with built-in method/, $_[0] }; + use lib 't/testlib'; + require Film; + require Actor; + Actor->has_a(film => 'Film'); + sub Class::DBI::sheep { ok 0; } +} + +sub Film::mutator_name { + my ($class, $col) = @_; + return "set_sheep" if lc $col eq "numexplodingsheep"; + return $col; +} + +sub Film::accessor_name { + my ($class, $col) = @_; + return "sheep" if lc $col eq "numexplodingsheep"; + return $col; +} + +sub Actor::accessor_name { + my ($class, $col) = @_; + return "movie" if lc $col eq "film"; + return $col; +} + +my $data = { + Title => 'Bad Taste', + Director => 'Peter Jackson', + Rating => 'R', +}; + +eval { + my $data = $data; + $data->{NumExplodingSheep} = 1; + ok my $bt = Film->create($data), "Modified accessor - with column name"; + isa_ok $bt, "Film"; +}; +is $@, '', "No errors"; + +eval { + my $data = $data; + $data->{sheep} = 1; + ok my $bt = Film->create($data), "Modified accessor - with accessor"; + isa_ok $bt, "Film"; +}; +is $@, '', "No errors"; + +eval { + my @film = Film->search({ sheep => 1 }); + is @film, 2, "Can search with modified accessor"; +}; + +{ + + eval { + local $data->{set_sheep} = 1; + ok my $bt = Film->create($data), "Modified mutator - with mutator"; + isa_ok $bt, "Film"; + }; + is $@, '', "No errors"; + + eval { + local $data->{NumExplodingSheep} = 1; + ok my $bt = Film->create($data), "Modified mutator - with column name"; + isa_ok $bt, "Film"; + }; + is $@, '', "No errors"; + + eval { + local $data->{sheep} = 1; + ok my $bt = Film->create($data), "Modified mutator - with accessor"; + isa_ok $bt, "Film"; + }; + is $@, '', "No errors"; + +} + +{ + my $p_data = { + name => 'Peter Jackson', + film => 'Bad Taste', + }; + my $bt = Film->create($data); + my $ac = Actor->create($p_data); + + eval { my $f = $ac->film }; + like $@, qr/film/, "no hasa film"; + + eval { + ok my $f = $ac->movie, "hasa movie"; + isa_ok $f, "Film"; + is $f->id, $bt->id, " - Bad Taste"; + }; + is $@, '', "No errors"; + + { + local $data->{Title} = "Another film"; + my $film = Film->create($data); + + eval { $ac->film($film) }; + ok $@, $@; + + eval { $ac->movie($film) }; + ok $@, $@; + + eval { + ok $ac->set_film($film), "Set movie through hasa"; + $ac->update; + ok my $f = $ac->movie, "hasa movie"; + isa_ok $f, "Film"; + is $f->id, $film->id, " - Another Film"; + }; + is $@, '', "No problem"; + } + +} + +SKIP: { # have non persistent accessor? + skip "Compat layer doesn't handle TEMP columns yet", 11; + Film->columns(TEMP => qw/nonpersistent/); + ok(Film->find_column('nonpersistent'), "nonpersistent is a column"); + ok(!Film->has_real_column('nonpersistent'), " - but it's not real"); + + { + my $film = Film->create({ Title => "Veronique", nonpersistent => 42 }); + is $film->title, "Veronique", "Title set OK"; + is $film->nonpersistent, 42, "As is non persistent value"; + $film->remove_from_object_index; + ok $film = Film->retrieve('Veronique'), "Re-retrieve film"; + is $film->title, "Veronique", "Title still OK"; + is $film->nonpersistent, undef, "Non persistent value gone"; + ok $film->nonpersistent(40), "Can set it"; + is $film->nonpersistent, 40, "And it's there again"; + ok $film->update, "Commit the film"; + is $film->nonpersistent, 40, "And it's still there"; + } +} + +SKIP: { # was bug with TEMP and no Essential + skip "Compat layer doesn't have TEMP columns yet", 5; + is_deeply( + Actor->columns('Essential'), + Actor->columns('Primary'), + "Actor has no specific essential columns" + ); + ok(Actor->find_column('nonpersistent'), "nonpersistent is a column"); + ok(!Actor->has_real_column('nonpersistent'), " - but it's not real"); + my $pj = eval { Actor->search(name => "Peter Jackson")->first }; + is $@, '', "no problems retrieving actors"; + isa_ok $pj => "Actor"; +} + +SKIP: { + skip "Compat layer doesn't handle read-only objects yet", 10; + Film->autoupdate(1); + my $naked = Film->create({ title => 'Naked' }); + my $sandl = Film->create({ title => 'Secrets and Lies' }); + + my $rating = 1; + my $update_failure = sub { + my $obj = shift; + eval { $obj->rating($rating++) }; + return $@ =~ /read only/; + }; + + ok !$update_failure->($naked), "Can update Naked"; + ok $naked->make_read_only, "Make Naked read only"; + ok $update_failure->($naked), "Can't update Naked any more"; + ok !$update_failure->($sandl), "But can still update Secrets and Lies"; + my $july4 = eval { Film->create({ title => "4 Days in July" }) }; + isa_ok $july4 => "Film", "And can still create new films"; + + ok(Film->make_read_only, "Make all Films read only"); + ok $update_failure->($naked), "Still can't update Naked"; + ok $update_failure->($sandl), "And can't update S&L any more"; + eval { $july4->delete }; + like $@, qr/read only/, "And can't delete 4 Days in July"; + my $abigail = eval { Film->create({ title => "Abigail's Party" }) }; + like $@, qr/read only/, "Or create new films"; + $SIG{__WARN__} = sub { }; +} + +SKIP: { skip "Lost a test adding skips somewhere, sorry", 2 } + diff --git a/t/cdbi-t/16-reserved.t b/t/cdbi-t/16-reserved.t new file mode 100644 index 0000000..7e67411 --- /dev/null +++ b/t/cdbi-t/16-reserved.t @@ -0,0 +1,31 @@ +use strict; +use Test::More; + +BEGIN { + eval "use DBD::SQLite"; + plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 5); +} + +use lib 't/testlib'; +require Film; +require Order; + +Film->has_many(orders => 'Order'); +Order->has_a(film => 'Film'); + +Film->create_test_film; + +my $film = Film->retrieve('Bad Taste'); +isa_ok $film => 'Film'; + +$film->add_to_orders({ orders => 10 }); + +my $bto = (Order->search(film => 'Bad Taste'))[0]; +isa_ok $bto => 'Order'; +is $bto->orders, 10, "Correct number of orders"; + + +my $infilm = $bto->film; +isa_ok $infilm, "Film"; + +is $infilm->id, $film->id, "Orders hasa Film"; diff --git a/t/cdbi-t/18-has_a.t b/t/cdbi-t/18-has_a.t new file mode 100644 index 0000000..84ee292 --- /dev/null +++ b/t/cdbi-t/18-has_a.t @@ -0,0 +1,235 @@ +use strict; +use Test::More; + +BEGIN { + eval "use DBD::SQLite"; + plan $@ ? (skip_all => 'needs DBD::SQLite for testing') : (tests => 41); +} + +use lib 't/testlib'; +use Film; +use Director; +@YA::Film::ISA = 'Film'; + +Film->create_test_film; + +ok my $btaste = Film->retrieve('Bad Taste'), "We have Bad Taste"; +ok my $pj = $btaste->Director, "Bad taste has a director"; +ok !ref($pj), ' ... which is not an object'; + +ok(Film->has_a('Director' => 'Director'), "Link Director table"); +ok( + Director->create({ + Name => 'Peter Jackson', + Birthday => -300000000, + IsInsane => 1 + } + ), + 'create Director' +); + +{ + ok $btaste = Film->retrieve('Bad Taste'), "Reretrieve Bad Taste"; + ok $pj = $btaste->Director, "Bad taste now hasa() director"; + isa_ok $pj => 'Director'; + { + no warnings 'redefine'; + local *Ima::DBI::st::execute = + sub { ::fail("Shouldn't need to query db"); }; + is $pj->id, 'Peter Jackson', 'ID already stored'; + } + ok $pj->IsInsane, "But we know he's insane"; +} + +# Oh no! Its Peter Jacksons even twin, Skippy! Born one minute after him. +my $sj = Director->create({ + Name => 'Skippy Jackson', + Birthday => (-300000000 + 60), + IsInsane => 1, + }); + +{ + eval { $btaste->Director($btaste) }; + like $@, qr/Director/, "Can't set film as director"; + is $btaste->Director->id, $pj->id, "PJ still the director"; + + # drop from cache so that next retrieve() is from db + $btaste->remove_from_object_index; +} + +{ # Still inflated after update + my $btaste = Film->retrieve('Bad Taste'); + isa_ok $btaste->Director, "Director"; + $btaste->numexplodingsheep(17); + $btaste->update; + isa_ok $btaste->Director, "Director"; + + $btaste->Director('Someone Else'); + $btaste->update; + isa_ok $btaste->Director, "Director"; + is $btaste->Director->id, "Someone Else", "Can change director"; +} + +is $sj->id, 'Skippy Jackson', 'Create new director - Skippy'; +Film->has_a('CoDirector' => 'Director'); +{ + eval { $btaste->CoDirector("Skippy Jackson") }; + is $@, "", "Auto inflates"; + isa_ok $btaste->CoDirector, "Director"; + is $btaste->CoDirector->id, $sj->id, "To skippy"; +} + +$btaste->CoDirector($sj); +$btaste->update; +is($btaste->CoDirector->Name, 'Skippy Jackson', 'He co-directed'); +is( + $btaste->Director->Name, + 'Peter Jackson', + "Didnt interfere with each other" +); + +{ # Inheriting hasa + my $btaste = YA::Film->retrieve('Bad Taste'); + is(ref($btaste->Director), 'Director', 'inheriting hasa()'); + is(ref($btaste->CoDirector), 'Director', 'inheriting hasa()'); + is($btaste->CoDirector->Name, 'Skippy Jackson', ' ... correctly'); +} + +{ + $sj = Director->retrieve('Skippy Jackson'); + $pj = Director->retrieve('Peter Jackson'); + + my $fail; + eval { + $fail = YA::Film->create({ + Title => 'Tastes Bad', + Director => $sj, + codirector => $btaste, + Rating => 'R', + NumExplodingSheep => 23 + }); + }; + ok $@, "Can't have film as codirector: $@"; + is $fail, undef, "We didn't get anything"; + + my $tastes_bad = YA::Film->create({ + Title => 'Tastes Bad', + Director => $sj, + codirector => $pj, + Rating => 'R', + NumExplodingSheep => 23 + }); + is($tastes_bad->Director->Name, 'Skippy Jackson', 'Director'); + is( + $tastes_bad->_director_accessor->Name, + 'Skippy Jackson', + 'director_accessor' + ); + is($tastes_bad->codirector->Name, 'Peter Jackson', 'codirector'); + is( + $tastes_bad->_codirector_accessor->Name, + 'Peter Jackson', + 'codirector_accessor' + ); +} + +SKIP: { + skip "Non-standard CDBI relationships not supported by compat", 9; + { + + YA::Film->add_relationship_type(has_a => "YA::HasA"); + + package YA::HasA; + use base 'Class::DBI::Relationship::HasA'; + + sub _inflator { + my $self = shift; + my $col = $self->accessor; + my $super = $self->SUPER::_inflator($col); + + return $super + unless $col eq $self->class->find_column('Director'); + + return sub { + my $self = shift; + $self->_attribute_store($col, 'Ghostly Peter') + if $self->_attribute_exists($col) + and not defined $self->_attrs($col); + return &$super($self); + }; + } + } + { + + package Rating; + + sub new { + my ($class, $mpaa, @details) = @_; + bless { + MPAA => $mpaa, + WHY => "@details" + }, $class; + } + sub mpaa { shift->{MPAA}; } + sub why { shift->{WHY}; } + } + local *Director::mapme = sub { + my ($class, $val) = @_; + $val =~ s/Skippy/Peter/; + $val; + }; + no warnings 'once'; + local *Director::sanity_check = sub { $_[0]->IsInsane ? undef: $_[0] }; + YA::Film->has_a( + director => 'Director', + inflate => 'mapme', + deflate => 'sanity_check' + ); + YA::Film->has_a( + rating => 'Rating', + inflate => sub { + my ($val, $parent) = @_; + my $sheep = $parent->find_column('NumexplodingSheep'); + if ($parent->_attrs($sheep) || 0 > 20) { + return new Rating 'NC17', 'Graphic ovine violence'; + } else { + return new Rating $val, 'Just because'; + } + }, + deflate => sub { + shift->mpaa; + }); + + my $tbad = YA::Film->retrieve('Tastes Bad'); + + isa_ok $tbad->Director, 'Director'; + is $tbad->Director->Name, 'Peter Jackson', 'Director shuffle'; + $tbad->Director('Skippy Jackson'); + $tbad->update; + is $tbad->Director, 'Ghostly Peter', 'Sanity checked'; + + isa_ok $tbad->Rating, 'Rating'; + is $tbad->Rating->mpaa, 'NC17', 'Rating bumped'; + $tbad->Rating(new Rating 'NS17', 'Shaken sheep'); + no warnings 'redefine'; + local *Director::mapme = sub { + my ($class, $obj) = @_; + $obj->isa('Film') ? $obj->Director : $obj; + }; + + $pj->IsInsane(0); + $pj->update; # Hush warnings + + ok $tbad->Director($btaste), 'Cross-class mapping'; + is $tbad->Director, 'Peter Jackson', 'Yields PJ'; + $tbad->update; + + $tbad = Film->retrieve('Tastes Bad'); + ok !ref($tbad->Rating), 'Unmagical rating'; + is $tbad->Rating, 'NS17', 'but prior change stuck'; +} + +{ # Broken has_a declaration + eval { Film->has_a(driector => "Director") }; + like $@, qr/driector/, "Sensible error from has_a with incorrect column: $@"; +} diff --git a/t/cdbi-t/19-set_sql.t b/t/cdbi-t/19-set_sql.t index 2b986bd..f3590d5 100644 --- a/t/cdbi-t/19-set_sql.t +++ b/t/cdbi-t/19-set_sql.t @@ -62,8 +62,6 @@ Film->set_sql( is $pgs[1]->id, $f4->id, "and F4"; }; -#SKIP: { -# skip "DBIx::Class doesn't have has_a yet", 6; { Actor->has_a(film => "Film"); Film->set_sql(