Skip Menu |

This queue is for tickets about the Tangram CPAN distribution.

Report information
The Basics
Id: 2741
Status: resolved
Worked: 1 hour (60 min)
Priority: 0/
Queue: Tangram

People
Owner: SAMV [...] cpan.org
Requestors: amackey [...] virginia.edu
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: 2.05



From: Aaron Mackey <AMACKEY [...] cpan.org>
To: bug-Tangram [...] rt.cpan.org
Subject: BackRef normalisation bug
Date: Thu, 5 Jun 2003 01:14:16 +1200
CC: Aaron J Mackey <ajm6q [...] virginia.edu>
[logged on behalf] I have class names like My::Project::DataType and My::Project::CollectionType ... in order for my database to take these names, I have a normalize sub that strips them to DataType and CollectionType; which is fine, until I go to use a Tangram::BackRef to access a CollectionType from a DataType - Tangram says "No such class 'CollectionType'", which is true: the class is "My::Project::CollectionType". I've tracked it down to lines 139-141 of Tangram/Schema.pm: $class = $self->{normalize}->($class, 'fieldname'); my @members = $types->{$typetag}->reschema($memdefs, $class, $self) if $memdefs; The "backref" handling is done within reschema, in which $class is now "CollectionType" instead of "My::Project::CollectionType". Later, in line 160, we do need the normalized table name. One fix would be to pass reschema an additional variable, the unmolested class name, to be used in backrefs ... I'm happy to provide that patch for those interested. [editor - patch bled out of user; see attached]

Message body is not shown because sender requested not to inline it.

RT-Send-CC: Aaron J Mackey <ajm6q [...] virginia.edu>
Aaron, just looking through the patch you sent me, I *think* that your patch is unnecessary with the latest release; your code here: $classdef->{members} = $classdef->{fields}; my $cols = 0; + my $oldclass = $class; # save for 'backref' below + $class = $self->{normalize}->($class, 'fieldname'); + foreach my $typetag (keys %{$classdef->{members}}) { my $memdefs = $classdef->{members}{$typetag}; That normalisation of the Class name is too early, I think. There's always a reference to $schema floating around, so instead of normalising the class name before passing into reschema, I normalise it inside reschema when I convert them to a column name, as below: sub reschema { my ($self, $members, $class, $schema) = @_; foreach my $member (keys %$members) { my $def = $members->{$member}; unless (ref($def)) { $def = { class => $def }; $members->{$member} = $def; } $def->{coll} ||= ($schema->{normalize}->($class) . "_$member"); $def->{slot} ||= ($schema->{normalize}->($class) . "_$member" . "_slot"); $schema->{classes}{$def->{class}}{stateless} = 0; if (exists $def->{back}) { my $back = $def->{back} ||= $def->{item}; $schema->{classes}{ $def->{class} }{members}{backref}{$back} = bless { name => $back, col => $def->{coll}, class => $class, field => $member }, 'Tangram::BackRef'; } } return keys %$members; } If you think that I've misinterpreted your problem, please restate or preferably build a test case in the t/array.t that demonstrates your problem. Cheers, Sam. [AMACKEY - Wed Jun 4 09:14:24 2003]: Show quoted text
> [logged on behalf] > > I have class names like My::Project::DataType and > My::Project::CollectionType ... in order for my database to take > these names, I have a normalize sub that strips them to DataType and > CollectionType; which is fine, until I go to use a Tangram::BackRef > to access a CollectionType from a DataType - Tangram says "No such > class 'CollectionType'", which is true: the class is > "My::Project::CollectionType". > > I've tracked it down to lines 139-141 of Tangram/Schema.pm: > > $class = $self->{normalize}->($class, 'fieldname'); > my @members = $types->{$typetag}->reschema($memdefs, $class, $self) > if $memdefs; > > The "backref" handling is done within reschema, in which $class is > now "CollectionType" instead of "My::Project::CollectionType". > > Later, in line 160, we do need the normalized table name. > > One fix would be to pass reschema an additional variable, the > unmolested class name, to be used in backrefs ... I'm happy to > provide that patch for those interested. > > [editor - patch bled out of user; see attached] >
From: amackey [...] virginia.edu
After going through the code, I believe your patch will have the same effect as mine, and is cleaner ... Thanks, -Aaron [SAMV - Mon Jun 9 08:51:20 2003]: Show quoted text
> Aaron, just looking through the patch you sent me, I *think* that your > patch is unnecessary with the latest release; your code here: > > > $classdef->{members} = $classdef->{fields}; > > > my $cols = 0; > > + my $oldclass = $class; # save for 'backref' below > + $class = $self->{normalize}->($class, 'fieldname'); > + > > foreach my $typetag (keys %{$classdef->{members}}) > > { > > my $memdefs = $classdef->{members}{$typetag}; > > That normalisation of the Class name is too early, I think. There's > always a reference to $schema floating around, so instead of normalising > the class name before passing into reschema, I normalise it inside > reschema when I convert them to a column name, as below: > > sub reschema > { > my ($self, $members, $class, $schema) = @_; > > foreach my $member (keys %$members) > { > my $def = $members->{$member}; > > unless (ref($def)) > { > $def = { class => $def }; > $members->{$member} = $def; > } > > $def->{coll} ||= ($schema->{normalize}->($class) > . "_$member"); > $def->{slot} ||= ($schema->{normalize}->($class) > . "_$member" . "_slot"); > > $schema->{classes}{$def->{class}}{stateless} = 0; > > if (exists $def->{back}) > { > my $back = $def->{back} ||= $def->{item}; > $schema->{classes}{ $def->{class} }{members}{backref}{$back} = > bless { > name => $back, > col => $def->{coll}, > class => $class, > field => $member > }, 'Tangram::BackRef'; > } > } > > return keys %$members; > } > > If you think that I've misinterpreted your problem, please restate or > preferably build a test case in the t/array.t that demonstrates your > problem. > > Cheers, > Sam. > > [AMACKEY - Wed Jun 4 09:14:24 2003]: >
> > [logged on behalf] > > > > I have class names like My::Project::DataType and > > My::Project::CollectionType ... in order for my database to take > > these names, I have a normalize sub that strips them to DataType and > > CollectionType; which is fine, until I go to use a Tangram::BackRef > > to access a CollectionType from a DataType - Tangram says "No such > > class 'CollectionType'", which is true: the class is > > "My::Project::CollectionType". > > > > I've tracked it down to lines 139-141 of Tangram/Schema.pm: > > > > $class = $self->{normalize}->($class, 'fieldname'); > > my @members = $types->{$typetag}->reschema($memdefs, $class, $self) > > if $memdefs; > > > > The "backref" handling is done within reschema, in which $class is > > now "CollectionType" instead of "My::Project::CollectionType". > > > > Later, in line 160, we do need the normalized table name. > > > > One fix would be to pass reschema an additional variable, the > > unmolested class name, to be used in backrefs ... I'm happy to > > provide that patch for those interested. > > > > [editor - patch bled out of user; see attached] > >
> >