On May 7, 2007, at 1:16 PM, Christopher H. Laco wrote:

and while it is all working now (thanks Claco!) I have to admit I
still find the behavior counter-intuitive at best.  I guess when I
was just inflating DateTime objects it made more sense, since the
inflated values were so much more complex than the representation
that was stored in the database, but when I started using
DBIx::Class::InflateColumn::Currency, it seemed odd to me that
'$10.00' would be inflated to a Data::Currency object if it came from=

the database, but not if it came from the user. I've fixed this for my immediate need by writing an HTML::FormFu::Inflator subclass that parallels DBIx::Class::InflateColumn::Currency, but going forward I'd=

like to avoid repeating so much code, so I've come up with an idea to=

extend DBIx::Class::InflateColumn to allow user-provided values to be=

inflated the same way that database values are.

Well, if you call $obj->inflated_field('$10.00');

then do $obj->inflated_field; the second call will return the inflated=

object.

I'm not sure I see what the problem you're trying to solve is?

[mst]

Well, if you call $obj->inflated_field('$10.00');

The problem is, that will never work. I could be wrong, but whatever you pass to inflated columns has to either be an inflated object, or a valid
value matching EXACTLY what the current DB supports.

In this case '$10.00' is neither a currency object, nor a valid value
for a db column of type float.

The same has always been true for DateTime fields (at least in my
experience):

$obj->col('1-2-2007')

will never work in database that don't grok that datetime format. But if
you pass in a DateTime object, all is well...


The problem is that it does sometimes work, and I think I've finally figured out why...

If you set the value with $obj->col( '$10.00' ), and then request the value with $obj->col, you do indeed get back an inflated value. Looking through the code however, it appears that the inflation is done by DBIx::Column::InflateColumn::get_inflated_column, meaning the value is inflated when you retrieve it, not when you set it.

What this means is that this will work as expected:

$obj->col( '$10.00' );
print ref( $obj->col )."\n"; # will print Data::Currency

However, this will _not_ work as expected:

$obj->col( '$10.00' );
$obj->update;

The reason the second one doesn't work has to do with the inner workings of get_inflated_column and set_inflated_column.

When you do this:  $obj->get_inflated_column( $col );

The get_inflated_column method will look for a previously inflated value in $self->{ _inflated_column }{ $col } and return it if it finds it, if it doesn't already have an inflated value, it will call get_column to retrieve the value from the database, inflate that, store it in $self->{ _inflated_column }{ $col } and return the inflated value.

When you do this: $obj->set_inflated_column( $col, Data::Currency->new ( 10, 'USD' ) );

The set_inflated_column method will deflate the object and call set_column with that value, so that other things that don't understand the inflated values will work correctly (things like DBIx::Class::Row::update for example).

When you do this: $obj->set_inflated_column( $col, '$10.00' ); is where things start to fall apart...

set_inflated_column will call _deflated_column with an argument of '$10.00', which gets returned unchanged because it isn't a reference, then it calls set_column with that value, thereby populating the object with invalid data. Now when you call $obj->update, update will call get_dirty_columns and pass the results to SQL::Abstract::update, but since the value was not inflated before it was deflated, the unchanged value is passed to the database and the update proceeds with invalid data.


I've been trying to determine the best way to fix this, but writing tests for it has proven difficult, I think I'm going to have to write a test class to inflate objects to...

--
Jason Kohles
[EMAIL PROTECTED]
http://www.jasonkohles.com/
"A witty saying proves nothing."  -- Voltaire



_______________________________________________
List: http://lists.rawmode.org/cgi-bin/mailman/listinfo/dbix-class
Wiki: http://dbix-class.shadowcatsystems.co.uk/
IRC: irc.perl.org#dbix-class
SVN: http://dev.catalyst.perl.org/repos/bast/trunk/DBIx-Class/
Searchable Archive: http://www.mail-archive.com/[email protected]/

Reply via email to