On 4/2/07, [EMAIL PROTECTED] wrote: > sub setup { > my ( $self, %arg_for ) = @_; > $self->SUPER::setup(%arg_for); > foreach my $column ( $self->columns ) { > my $name = $column->name; > > # here's the problem > $self->alias_column( $name => "_$name" ) > unless $self->class->is_public($column);
At this point (after calling SUPER::setup()), the column methods have already been created, so aliasing a columns will not do what you want unless you then re-initialize() or otherwise re-make the column methods, overriding the existing methods. But there's a better time to do this kind of thing. When mucking with Metadata subclasses, the rule of thumb is to override the most specific method possible. setup() is the least specific method (i.e., it's the highest level). If you want to twiddle columns, I suggest overriding add_columns() and getting them as soon as they come into being: sub add_columns { my($self) = shift; my @added_columns = $self->SUPER::add_columns(@_); foreach my $column (@added_columns ) { $self->alias_column($column->name => '_' . $column->name) unless($self->class->is_public($column)); } return @added_columns ; } (The return value for add_columns() wasn't documented, but has always been the list of columns just added. It's documented in SVN.) > So somehow, when aliasing a column, column_mutator_method_names_hash() > appears to return incorrect values or, perhaps, @$column_names is > getting incorrect values. I'll dig into this more later, but if anyone > can offer insight, I'd appreciate it. I suspect this is a side-effect of aliasing columns after the column methods have already been created. The cache of mutator method names is wiped, but then never repopulated (as it would be if the column methods were explicitly re-created after aliasing-too-late). Anyway, all this is side-stepped by aliasing the columns as soon as possible, rather than after the entire setup process has finished. > # XXX There should be a simpler way to push this into the base class. > # I have an idea of how to do it, but for now, I'll table it. > __PACKAGE__->meta->make_manager_class('os'); This is actually one thing you can and should do after the entire Rose::DB::Object-derived class is entirely set up. So here you could override setup() and add the appropriate make_manager_class() call at the end. > Note: the 'Readonly' class merely makes the mutators throw exceptions > if called. If I understand your intent correctly, and you really never want to be able to set certain columns at all from Perl-land, another possible technique is to simply create accessor-only methods for them. That is, just "get" methods instead of the usual "get_set" methods. Each column (and fk and relationship) can have zero or more methods created on behalf of it. By default, each column has one method, a "get_set" method created for it. Read more here: http://search.cpan.org/dist/Rose-DB-Object/lib/Rose/DB/Object/Metadata/Column.pm#MAKING_METHODS So, here's an alternate implementation off the top of my head: sub add_columns { my($self) = shift; my @columns = $self->SUPER::add_columns(@_); foreach my $column (@columns) { unless($self->class->is_public($column)) { $column->auto_method_types('get'); # only create accessor } } return @columns; } Unfortunately, most 'get' methods will not throw an exception if you pass an arg; they'll just ignore any args. Of course, you can always alias the column and only create a get method and then *also* create an exception-thrower under the usual name: sub add_columns { my($self) = shift; my @columns = $self->SUPER::add_columns(@_); foreach my $column (@columns) { unless($self->class->is_public($column)) { my $name = $column->name; my $mangled = "_$name"; # alias column $self->alias_column($name => $mangled); # only create accessor $column->auto_method_types('get'); unless($self->class->can($name)) { # Create exception-thrower under unmangled name no strict 'refs'; *{"${class}::$name"} = sub { my($self) = shift; croak "No args, please..." if(@_); $self->$mangled(); }; } } } return @columns; } Hm, that's kind of ugly. Anyway, TMTOWTDI :) -John ------------------------------------------------------------------------- Take Surveys. Earn Cash. Influence the Future of IT Join SourceForge.net's Techsay panel and you'll get the chance to share your opinions on IT & business topics through brief surveys-and earn cash http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV _______________________________________________ Rose-db-object mailing list Rose-db-object@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/rose-db-object