On May 12, 6:27 am, byrnejb <[email protected]> wrote:
> We have an ActiveRecord model class which is choking on an attribute
> that has both a default value of 'infinity' and a NOT NULL
> constraint. Basically, AR tries to insert a NULL because Ruby does
> not understand 'infinity' and AR explicitly sets all columns with
> defaults to those values (when it understands them) when inserting a
> row.
>
> I am contemplating moving this class to Sequel but I would like to
> know whether Sequel handles this situation any differently?
Sequel::Model typecasting uses Kernel#Float by default, which doesn't
appear to like 'infinity':
DB.create_table!(:a){Float :a}
Sequel::Model(:a).new.a = 'infinity'
Sequel::InvalidValue: ArgumentError: invalid value for Float():
"infinity"
You can disable such typecasting errors, and you'll be able to save
records:
Sequel::Model.raise_on_typecast_failure = false
DB.create_table!(:a){Float :a}
a = Sequel::Model(:a).create(:a => 'infinity')
Unfortunately, while that will save an infinite float, loading the
record won't get you the same result:
a.a # => 0.0
This is because String#to_f is used on retrieval, and "Infinity".to_f
results in 0.0.
The good news is that if you modify String#to_f, things will work
fine:
class String
alias old_to_f to_f
def to_f() self =~ /\A([+-])?infinity\z/i ? (Float::MAX * (($1 ==
'-' ) ? -2 : 2)) : old_to_f end
end
Until you try to update an existing record, as Sequel doesn't
literalize infinite floats properly. That's possible to fix too:
class Sequel::Dataset
alias old_literal_float literal_float
def literal_float(v) v.infinite? ? literal("#{'-' if v < 0}
infinity") : old_literal_float(v) end
end
And patching Kernel#Float will make typecasting work correctly:
module Kernel
alias old_Float Float
def Float(v) v =~ /\A([+-])?infinity\z/i ? (Float::MAX * (($1 ==
'-' ) ? -2 : 2)) : old_Float(v) end
end
With the modifications to String#to_f, Kernel#Float, and
Sequel::Dataset, you should be able to handle things correctly. I'm
open to making the Sequel::Dataset modification part of Sequel, but
I'm not sure that's wise until ruby itself fixes String#to_f and
Kernel#Float.
I should point out that if you are using sequel_pg, the retrieval
probably won't be fixable without modifying the extension, as does the
type conversion in C:
rv = rb_float_new(rb_cstr_to_dbl(v, Qfalse));
Jeremy
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sequel-talk?hl=en.