Are the strings OK (i.e., in a known, consistent encoding and not
mangled) when you call the column accessor methods on the RDBO-derived
object even without your custom column subclass code??
-John
OK, so it sounds to me like the problem is with the other code that
processes these strings. Checking to see if Perl's UTF-8 flag is on
is not a good way to check if a string contains UTF-8-encoded data.
If some module is doing that and you can't stop it or otherwise
convince it that what you're feeding it is already a UTF-8-encoded
string, then can you add the extra filtering/mangling step between
that problematic API and the data you're feeding it? IOW, does all
data in every RDBO class need to be marked as UTF-8 as it exits the
column accessor, or does it just need to be done so this one consumer
of this data will behave correctly?
All of that said, I'm not opposed to adding this kind of thing as a
built-in filter on columns. But it sounds to me like you're already
basically doing that, so I'm not sure what advantage you'd get from
having it part of the module. Would that let you drop all your column
subclasses? If so, feel free to submit a patch to add this feature to
the base string column class.
-John
How about marking them as they come out of the objects via the column
accessor methods? You could do that with an on_get trigger, and you
could add those column triggers automatically to all text columns at
class construction time.
If you really wanted to mess with the value as it's stored in the
object, you could use on_load triggers.
http://search.cpan.org/dist/Rose-DB-Object/lib/Rose/DB/Object/Metadata/Column.pm#TRIGGERS
-John
Create your own Rose::DB::Object::Metadata subclass (if you don't have
one already) and make it the meta_class for your common
Rose::DB::Object base class. Then override add_columns() in your
custom Metadata subclass and apply the trigger(s) to the appropriate
column(s). (You should be able to call the SUPER:: method to do all
the work, catching the return value, then just walk over the newly
constructed columns and add your triggers.)
http://search.cpan.org/dist/Rose-DB-Object/lib/Rose/DB/Object.pm#meta_class
http://search.cpan.org/dist/Rose-DB-Object/lib/Rose/DB/Object/Metadata.pm#add_columns
-John
…of course, once you have your own Metadata subclass, why not just
make your own column subclasses that have these triggers automatically
self-applied, then update the column_type_class() for the relevant
column types (or make new column type name(s)) and then just build
your classes as usual, using whatever type name(s) correspond to your
new UTF-8-ifying column class(es)?
-John
Overriding init() and calling add_builtin_trigger() to add your
trigger(s) should work.
-John
Call the column's accessor method. Triggers should be disabled when
you're inside a trigger sub, so there should not be infinite
recursion.
-John
Also, your call to SUPER:: assumes that the init() method is called in
scalar context. This is probably fine, but in general you should
preserve the calling context when trying to transparently wrap a
function. (There are CPAN modules to do this in fewer lines of code
than you'd have to write yourself to do it "manually.")
-John
I don't remember; I was making a general statement. But it's never
wrong to do it right :)
> $self->rw_method_name returns undef outside of the trigger.
Ah, maybe it's not set yet at that point. Still, you can hoist the
declaration of $accessor_name and then use ||= inside the trigger sub.
-John