gshank / dbix-class-resultset-recursiveupdate Goto Github PK
View Code? Open in Web Editor NEWDBIx::Class::ResultSet::RecursiveUpdate
DBIx::Class::ResultSet::RecursiveUpdate
Running HARNESS_OPTIONS=j make test
will result in test failures because multiple tests try to access the same database file.
Hello.
I tried the example of has_many read POD.
http://search.cpan.org/~gshank/DBIx-Class-ResultSet-RecursiveUpdate-0.34/lib/DBIx/Class/ResultSet/RecursiveUpdate.pm#Treatment_of_has_many_relations
Example of "Passing hashrefs:" worked.
But cases of "Passing ids:" did not work.
It was confirmed by adding code to t/01_basic.t.
% git diff
diff --git a/t/01_basic.t b/t/01_basic.t
index 8f31dde..db89bfd 100644
--- a/t/01_basic.t
+++ b/t/01_basic.t
@@ -282,6 +282,16 @@ is( $schema->resultset('Address')->search( { user_id => $user->id } )->count,
$dvd = $dvd_rs->find(1);
is( $dvd->get_column('owner'), $user->id, 'foreign key set' );
+$user_rs->recursive_update({
+ id => $user->id,
+ address => {
+ street => "101 Main Street",
+ city => "Podunk",
+ state => "New York"
+ },
+ owned_dvds => [ 1 ]
+});
+
# has_many where foreign cols are nullable
my $available_dvd_rs = $dvd_rs->search( { current_borrower => undef } );
$dvd_rs->update( { current_borrower => $user->id } );
Is the output.
% prove -I lib -v t/01_basic.t
t/01_basic.t .. testing dbi:SQLite:dbname=t/var/dvdzbr.db
ok 1 - fixed_fields pre 0.21 api ok
ok 2 - fixed_fields 0.21+ api ok
...
ok 43 - the right number of addresses
ok 44 - foreign key set
DBIx::Class::ResultSet::RecursiveUpdate::recursive_update(): first parameter needs to be a hashref at t/01_basic.t line 285
# Tests were run but no plan was declared and done_testing() was not seen.
Dubious, test returned 255 (wstat 65280, 0xff00)
All 44 subtests passed
Test Summary Report
-------------------
t/01_basic.t (Wstat: 65280 Tests: 44 Failed: 0)
Non-zero exit status: 255
Parse errors: No plan found in TAP output
Files=1, Tests=44, 1 wallclock secs ( 0.04 usr 0.00 sys + 0.72 cusr 0.08 csys = 0.84 CPU)
Result: FAIL
Document is correct?
Or code is correct?
I would appreciate your answer.
Cheers,
Tomohiro Hosaka
I have a correlated column, which appears in {_column_data}
, and I am assuming the module does not check for whether the column is a real column defined in ResultSource, or if it is a correlated column. It tries to update it regardless, and results in an error "column does not exist".
There often may be cases where a table is bound to an integer id PK, but the "real" key is the name, which is uniquely constrained. And in those cases, you might not know the integer PK. For example:
owner => { name => "Thing" },
Thing
already exists, so trying to INSERT this would error. However, DBIC:RS:RU isn't going to find the row, despite given a proper unique key to find it. So, you end up with an uniqueness error because it tries to INSERT it.
The $object
find should look for all keys, not just PKs. I have a partial solution here:
for my $constraint (
sort { $b eq 'primary' ? 1 : $a eq 'primary' ? -1 : $a cmp $b } # make primary first
$source->unique_constraint_names) {
last if defined $object;
# the updates hashref might contain the constraint columns
# but with an undefined value
my @missing =
grep { !defined $updates->{$_} && !exists $fixed_fields{$_} }
$source->unique_constraint_columns($constraint);
#warn "MISSING $constraint: " . join(', ', @missing) . "\n";
unless ( @missing ) {
warn 'finding by: ' . Dumper( $updates ); use Data::Dumper;
$object = $self->find( $updates, { key => $constraint } );
}
last if defined $object;
# add the resolved columns to the updates hashref
$updates = { %$updates, %$resolved };
# the resolved hashref might contain the constraint columns
# but with an undefined value
@missing = grep { !defined $resolved->{$_} } @missing;
#warn "MISSING2 $constraint: " . join( ', ', @missing ) . "\n";
unless ( @missing ) {
warn 'finding by +resolved: ' . Dumper( $updates ); use Data::Dumper;
$object = $self->find( $updates, { key => $constraint } );
}
}
This works, but it's flawed in regards to the more complicated test cases. I think this is because the other primary_column
cases haven't been converted yet. I need help with these because I don't completely understand what they do.
On the other hand, I do have a test case written for my problem above (96multi_create.t
):
diag '* second create_related with same arguments';
eval {
my $artist = $schema->resultset('Artist')->first;
my $cd_result = $schema->resultset('CD')->recursive_update(
{
artist => $artist->artistid,
title => 'TestOneCD2',
year => 2007,
tracks => [
{ pos => 111,
title => 'TrackOne',
},
{ pos => 112,
title => 'TrackTwo',
}
],
liner_notes => { notes => 'I can haz liner notes?' },
genre => { name => 'TestGenre' }
}
);
ok( $cd_result && ref $cd_result eq 'DBICTest::CD', "Got Good CD Class" );
ok( $cd_result->title eq "TestOneCD2", "Got Expected Title" );
ok( $cd_result->notes eq 'I can haz liner notes?', 'Liner notes' );
my $tracks = $cd_result->tracks;
ok( $tracks->isa("DBIx::Class::ResultSet"),
"Got Expected Tracks ResultSet"
);
foreach my $track ( $tracks->all ) {
ok( $track && ref $track eq 'DBICTest::Track',
'Got Expected Track Class' );
}
};
diag $@ if $@;
diag '* third create_related with non-primary unique key';
eval {
my $artist = $schema->resultset('Artist')->first;
my $cd_result = $schema->resultset('CD')->recursive_update(
{
artist => $artist->artistid,
title => 'TestOneCD2',
year => 2007,
tracks => [
{ pos => 111,
title => 'TrackOne',
},
{ pos => 112,
title => 'TrackTwo',
}
],
liner_notes => { notes => 'I can haz liner notes?' },
genre => { name => 'TestGenre' }
}
);
ok( $cd_result && ref $cd_result eq 'DBICTest::CD', "Got Good CD Class" );
ok( $cd_result->title eq "TestOneCD2", "Got Expected Title" );
ok( $cd_result->notes eq 'I can haz liner notes?', 'Liner notes' );
ok( $cd_result->genre->name eq 'TestGenre', 'Got Expected Genre' );
my $tracks = $cd_result->tracks;
ok( $tracks->isa("DBIx::Class::ResultSet"),
"Got Expected Tracks ResultSet"
);
foreach my $track ( $tracks->all ) {
ok( $track && ref $track eq 'DBICTest::Track',
'Got Expected Track Class' );
}
};
diag $@ if $@;
(The second create_related
block is the same as the original with the added genre. The third create_related
is a new test.)
The expected behaviour is for the row outputted from recursive_update to correctly show the nested belongs_to relationship. The actual behaviour is that it seems to lose the change in the returned row, despite correctly updating the DB.
This patch adds a test and changes a couple test schema tables:
liner_notes
table changed to use dvd_id
as it's PKliner_notes_belongs_to
table with belongs_to relationship to liner_notes
In the test, I've added comments where you can comment out a line to make the test pass. When I dug into the RecursiveUpdate code, in _update_relation
when it calls set_from_related
, it passes in the correct data, but the output from get_columns
afterwards is unchanged, for example:
$sub_object->get_columns() = {
'dvd_id' => 5,
'notes' => 'test note',
'liner_notes_belongs_to' => 1
};
Now $object->set_from_related($name, $sub_object) is called and then:
$sub_object->get_columns() = {
'dvd_id' => 5,
'notes' => 'test note',
'liner_notes_belongs_to' => undef
};
I tried a simpler test with just the liner_notes and liner_notes_belongs_to, but they worked fine... It only stops working when I add the extra layer of the DVD.
Hello.
I'll make the question simple.
It seems that RU doesn't work unless schema is rel_name == pk naming in case of many_to_many from 0.40.
The output of the test is below.
https://github.com/bokutin/recursiveupdate-test/blob/master/out.txt
The schema is below.
https://github.com/bokutin/recursiveupdate-test/tree/master/t/lib/M2MTest
Is my usage wrong?
I think I am using it as DESIGN CHOICES - Treatment of many-to-many pseudo relations.
It would be greatly appreciated if someone could answer.
uses non-destructive substitution (s//r) which was added in 5.14
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.