Re: [RDBO] Read-only objects
call me lazy-- I just use a bad db handle for all things rose, then have a custom method that pulls a read-only or read/write handle from a db factory as needed. ie, they'll always fail on save, insert, update because they don't have the db permissions - 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
Re: [RDBO] Read-only objects
On 4/4/07 12:37 PM, Adrian Howard wrote: > Since there are at least three folk who have wanted this sort of > functionality - would it be worth adding something like > is_initialising() to Rose::DB::Object::Util? Just to prevent > gratuitous wheel reinvention :-) No, since that'd require extra overhead for all RDBO-derived objects. Better to make Rose::DB::Object::ReadOnly or something similar which would override init() as shown and add an exception on_set for every column when not init()ializing. Anyone should feel free to code, document, and write tests for such a thing and then submit it to me :) -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
Re: [RDBO] Read-only objects
On 4 Apr 2007, at 17:21, John Siracusa wrote: [snip] > The only way to distinguish the two is by calling context. That > said, there > are (slightly) better ways to detect the context than using caller(). > Here's what I suggest: > > # Override init in you common base class > # (See the Rose::Object docs for details) > sub init > { > my($self) = shift; > local $self->{'__allow_set'} = 1; # or whatever attr name you > pick > $self->SUPER::init(@_); > } [snip] > Granted, this is still a bit of a hack, but at least it only relies on > public APIs, rather than internal implementation details. [snip] I've done something similar myself. Since there are at least three folk who have wanted this sort of functionality - would it be worth adding something like is_initialising() to Rose::DB::Object::Util? Just to prevent gratuitous wheel reinvention :-) Adrian - 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
Re: [RDBO] Read-only objects
On 4/4/07 12:05 PM, Ovid wrote: > Note the 'return' condition. I found that if I didn't have that in, > the following would throw an exception: > > my $os = Donhost::OS->new( os => 'ubuntu' ); > > The hack guarantees that only things like the following throwing > exceptions: > > $os->os('windows'); > $os->description('sucks'); > > The hack relies on the order of call stack frames being different when > I'm constructing an object or just setting an accessor directly. How > can I do this without relying on the internals like this? The problem is that this: $o = Foo->new(a => 123) is really this: $o = Foo->new; $o->a(123); The only way to distinguish the two is by calling context. That said, there are (slightly) better ways to detect the context than using caller(). Here's what I suggest: # Override init in you common base class # (See the Rose::Object docs for details) sub init { my($self) = shift; local $self->{'__allow_set'} = 1; # or whatever attr name you pick $self->SUPER::init(@_); } Then, in your trigger, replace this: my ($called_from) = caller(1); return if $called_from eq 'Rose::Object'; with this: return if shift->{'__allow_set'}; Granted, this is still a bit of a hack, but at least it only relies on public APIs, rather than internal implementation details. -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
Re: [RDBO] Read-only objects
> "Ovid" == Ovid <[EMAIL PROTECTED]> writes: Ovid> The hack relies on the order of call stack frames being different when Ovid> I'm constructing an object or just setting an accessor directly. How Ovid> can I do this without relying on the internals like this? It seems like everyone using RDBO reinvents the same things. Hooray for this mailing list! Here's what I did for my readonly class, based on discussions with jcs six months ago: sub insert { die "cannot insert" unless our $READWRITE; goto &{$_[0]->can("SUPER::insert")}; } sub update { die "cannot update" unless our $READWRITE; goto &{$_[0]->can("SUPER::update")}; } sub delete { die "cannot delete" unless our $READWRITE; goto &{$_[0]->can("SUPER::delete")}; } I use "local our $READWRITE = 1" during some test harnesses when I set up a fake version of the database. Apparently, everything else is built on these routines, so unless you call something even *lower* in your own code, this is enough to trap everything that RDBO is doing "out of the box". -- Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095 http://www.stonehenge.com/merlyn/> Perl/Unix/security consulting, Technical writing, Comedy, etc. etc. See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training! - 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
Re: [RDBO] Read-only objects
--- Ovid <[EMAIL PROTECTED]> wrote: > My 'read-only' objects now have their very own metadata class. As a side note, it might be nice if a 'readonly' metadata class were natively available in Rose::DB::Object, with an optional way of allowing it to be read/write. I know I can create said objects with a Rose::DB subclass with only SELECT permissions, but that means the errors won't get thrown until I try to write to the database. Having them thrown as soon as I try to set an attribute would make debugging much easier. Cheers, Ovid -- Buy the book -- http://www.oreilly.com/catalog/perlhks/ Perl and CGI -- http://users.easystreet.com/ovid/cgi_course/ - 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
[RDBO] Read-only objects
My 'read-only' objects now have their very own metadata class. Trying to update from the 'save', 'insert', 'update', etc. now fails. I also have the accessors throwing Exception::Class objects if someone tries to set an attribute value. However, it's a nasty hack because the other code examples I saw here were failing: sub add_columns { my ( $self, @columns ) = @_; $self->SUPER::add_columns(@columns); my $class = $self->class; foreach my $column ( $self->columns ) { $column->add_trigger( event => 'on_set', code => sub { my ($called_from) = caller(1); my $attribute = $class->_attribute_name($column); return if $called_from eq 'Rose::Object'; throw_read_only "Attribute '$attribute' is read-only"; }, ); } } (I don't rely on the return value of $self->SUPER::add_columns(@columns) because we're only using the CPAN version) Note the 'return' condition. I found that if I didn't have that in, the following would throw an exception: my $os = Donhost::OS->new( os => 'ubuntu' ); The hack guarantees that only things like the following throwing exceptions: $os->os('windows'); $os->description('sucks'); The hack relies on the order of call stack frames being different when I'm constructing an object or just setting an accessor directly. How can I do this without relying on the internals like this? Cheers, Ovid -- Buy the book -- http://www.oreilly.com/catalog/perlhks/ Perl and CGI -- http://users.easystreet.com/ovid/cgi_course/ - 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