I am using a legacy database with mysql.
I am working stuff through in the console and it tells me…
@price = Price.find(:first, :conditions => [“stockid = ? AND typeabbrev
= ?”, @test, “WH”]).price
=> #<Price price: #BigDecimal:b7a7341c,‘0.115E1’,8(12)>
So I need to coerce this into a float…
I added to app/controllers/application_controller.rb (at the very bottom
of the file)…
Provides extension to Numerics to provide subject decimal places
class Float
def to_fl(digits)
sprintf("%.#{digits}f",self)
end
end
which used to work fine for me in Rails 1.2.6…but in the 2.3.2
console…
@price.to_i
=> 1
@price.to_fl(2)
NoMethodError: undefined method `to_fl’ for
#BigDecimal:b794c0fc,‘0.115E1’,8(12)
from (irb):30
from :0
How do I get the float value of ‘big decimal’ ?
Craig
–
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Craig W. wrote:
[…]
NoMethodError: undefined method `to_fl’ for
#BigDecimal:b794c0fc,‘0.115E1’,8(12)
from (irb):30
from :0
How do I get the float value of ‘big decimal’ ?
Perhaps you should have checked the class documentation for BigDecimal
(part of the Ruby standard library). If I remember correctly,
BigDecimal#to_f will do what you want.
to_f is the standard name for such methods; to_fl is idiosyncratic, and
will cause problems if the consumers of your API expect to_f.
Best,
Marnen Laibow-Koser
http://www.marnen.org
[email protected]
Craig
On Wed, 2009-06-03 at 07:07 +0200, Marnen Laibow-Koser wrote:
Perhaps you should have checked the class documentation for BigDecimal
(part of the Ruby standard library). If I remember correctly,
BigDecimal#to_f will do what you want.
to_f is the standard name for such methods; to_fl is idiosyncratic, and
will cause problems if the consumers of your API expect to_f.
yeah, I’m sort of stuck in a rails 1.2.x time warp and am struggling
with a bunch of the changes in 2.3.x - thus, it wasn’t really the big
decimal thing of mysql that was the problem.
I forgot about to_f because frankly, I never used it. I primarily am
concerned with view code here so I had just stuck that code to extend
the Float class (which worked so well in 1.2.x)…
class Float
def to_fl(digits)
sprintf("%.#{digits}f",self)
end
end
and I could get a fixed number of digits whenever I wanted. Apparently
this is like a very ineffective way to go about things in 2.3.x and to_f
gives me whatever decimal places it believes are significant so I’m sort
of trying to figure out how to locate the magic genie again.
Craig
–
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
The problem is that you’re defining this method (to_fl) on Float,
while AR is returning you a BigDecimal. Have you tried defining the
method in the correct class?
You don’t appear to really want the “float value”; for large numbers,
it will lose a lot of precision (and thus the advantage of storing in
a :decimal column).
–Matt J.
2009/6/3 Craig W. [email protected]:
and I could get a fixed number of digits whenever I wanted. Apparently
this is like a very ineffective way to go about things in 2.3.x and to_f
gives me whatever decimal places it believes are significant so I’m sort
of trying to figure out how to locate the magic genie again.
Craig
I am not sure whether you still have a problem. It is not strictly
correct to say that to_f gives me whatever decimal places it believes
are significant. A float will always contain as many digits as it can
hold. Is the problem that you wish to display it to a certain number
of digits? If so then you can use sprintf.
Alternatively of course there is the question of whether you need to
convert it to a float in the first place. Can you just keep it as
BigDecimal?
Colin
Thanks - I see said the blind man…
all I had to do was to first convert big decimal to float and then the
sprint function worked.
@price.to_f.to_fl(2) and I get what I wanted in the view…something
displayed to 2 decimal places. The value is already stored with
big_decimal precision…I just didn’t know how to format it in a view,
which turned out to be trickier than if I just a float value.
Craig
On Wed, 2009-06-03 at 06:59 -0700, Matt J. wrote:
class Float
Craig
–
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Craig W. wrote:
Thanks - I see said the blind man…
all I had to do was to first convert big decimal to float and then the
sprint function worked.
@price.to_f.to_fl(2) and I get what I wanted in the view…
Your Float#to_fl method is unnecessary and has semantics that will
confuse experienced Ruby programmers. Try @price.round(2).to_f.
Best,
Marnen Laibow-Koser
http://www.marnen.org
[email protected]
On Wed, 2009-06-03 at 19:36 +0200, Marnen Laibow-Koser wrote:
Craig W. wrote:
Thanks - I see said the blind man…
all I had to do was to first convert big decimal to float and then the
sprint function worked.
@price.to_f.to_fl(2) and I get what I wanted in the view…
Your Float#to_fl method is unnecessary and has semantics that will
confuse experienced Ruby programmers. Try @price.round(2).to_f.
well, the round(2) function will return 1.5 if that is the stored value
in big decimal which was unacceptable but I didn’t try
@price.round(2).to_f but I wonder which is faster/slower.
In reality, though, it tossed an error…
undefined method `round’ for #Price:0xb6e1bf20
which I think is back to my original problem of having a big decimal,
that must be converted to a float before it can be rounded.
Craig
–
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
Craig W. wrote:
[…]
well, the round(2) function will return 1.5 if that is the stored value
in big decimal which was unacceptable
Huh? I don’t understand what you’re saying.
but I didn’t try
@price.round(2).to_f but I wonder which is faster/slower.
In reality, though, it tossed an error…
Again, I don’t understand. Did you try it or not?
undefined method `round’ for #Price:0xb6e1bf20
which I think is back to my original problem of having a big decimal,
that must be converted to a float before it can be rounded.
No. BigDecimal#round should work as I just explained – at least it
does on my system. Are you sure @price is actually holding a
BigDecimal?
Craig
Best,
Marnen Laibow-Koser
http://www.marnen.org
[email protected]
On Wed, 2009-06-03 at 23:49 +0200, Marnen Laibow-Koser wrote:
No. BigDecimal#round should work as I just explained – at least it
does on my system. Are you sure @price is actually holding a
BigDecimal?
console session…
_>> @price = Price.find(:first, :conditions => [“stockid = ?”,
“F34/CW/ES”])
=> #<Price stockid: “F34/CW/ES”, typeabbrev: “RE”, currabrev: “USD”,
debtorno: " ", price: #BigDecimal:b7dc83ec,‘0.15E1’,8(12), branchcode:
" ">
_>> @price.price
=> #BigDecimal:b7dacaac,‘0.15E1’,8(12)
_>> @price.price.round(2)
=> #BigDecimal:b7d9a4b0,‘0.15E1’,8(16)
_>> @price.price.round(2).to_f
=> 1.5
_>> @price.price.round(2).to_fl(2)
NoMethodError: undefined method `to_fl’ for
#BigDecimal:b7ee9f64,‘0.15E1’,8(16)
from (irb):8
_>> @price.price.round(2).to_f.to_fl(2)
=> “1.50”
_>> @price.price.to_f.to_fl(2)
=> “1.50”
_>> @price.price.to_f.round(2)
=> 1.5
Craig
–
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.
On Jun 3, 2009, at 7:12 PM, Craig W. wrote:
but I didn’t try
decimal,
=> #<Price stockid: “F34/CW/ES”, typeabbrev: “RE”, currabrev: “USD”,
NoMethodError: undefined method `to_fl’ for
#BigDecimal:b7ee9f64,‘0.15E1’,8(16)
from (irb):8
_>> @price.price.round(2).to_f.to_fl(2)
=> “1.50”
_>> @price.price.to_f.to_fl(2)
=> “1.50”
_>> @price.price.to_f.round(2)
=> 1.5
Craig
I think you two are talking past each other a bit.
Marnen is describing BigDecimal correctly:
irb> require ‘bigdecimal’
=> true
irb> x = BigDecimal.new(“1.50”)
=> #BigDecimal:8569c,‘0.15E1’,8(8)
irb> x.to_s
=> “0.15E1”
irb> x.round(2)
=> #BigDecimal:802b4,‘0.15E1’,8(16)
irb> x.round(2).to_f
=> 1.5
irb> “%.2f”%[x.round(2)]
=> “1.50”
irb> x = BigDecimal.new(“1.5431”)
=> #BigDecimal:6b0d0,‘0.15431E1’,8(12)
irb> x.round(2)
=> #BigDecimal:6845c,‘0.154E1’,8(16)
irb> x.round(2).to_f
=> 1.54
irb> “%.2f”%[x.round(2)]
=> “1.54”
However, Craig, you seem to want a formatted output for your Price
model where the #price attribute happens to be a BigDecimal.
class Price
def formatted
“%.2f”%[self.price.round(2)]
end
end
Then you should have:
@price = Price.find(:first, :conditions => [“stockid = ?”,“F34/CW/
ES”])
@price.formatted
=> “1.50”
You might also want to roll your own helper similar to
number_to_currency
-Rob
Rob B. http://agileconsultingllc.com
[email protected]