4

i have

string = "$575.00 "
string.to_f
// => 0.0

string = "575.00 "
string.to_f
// => 575.0

the value coming in is in this format and i need to insert into a database field that is decimal any suggestions

"$575.00 " 
apaderno
  • 28,547
  • 16
  • 75
  • 90
Matt Elhotiby
  • 43,028
  • 85
  • 218
  • 321
  • 2
    Check out this gem: http://github.com/tobi/money_column – Joseph Yaduvanshi Aug 29 '10 at 19:52
  • 1
    You have answers telling you how to remove the dollar sign, but only one person mentioned that you shouldn't use float for money. Float (as defined by IEEE) is not precise, and when you are dealing with money, you need to be precise (you can't be losing people's money every time you do some math). To see my point, try `puts( 0.2-0.1 , 1.2-0.1 , 1.2-1.1 )` Without knowing more about your use case, I don't know what to suggest instead. – Joshua Cheek Aug 30 '10 at 02:14
  • @Joshua, good suggestion: `dollars, cents = string[1..-1].delete(',').split(/./).collect {|i| i.to_i(10)}` – glenn jackman Aug 30 '10 at 14:37
  • Yep, you should check out [flt (github)](http://github.com/jgoizueta/flt/) if you need industry-strength floating point / decimal point precision. This _especially_ matters once you start doing math with the values. – wuputah Aug 30 '10 at 20:17

5 Answers5

5

We did this so often we wrote an extension to String called cost_to_f:

class String
  def cost_to_f
    self.delete('$,').to_f
  end
end

We store such extensions in config/initializers/extensions/string.rb.

You can then simply call:

"$5,425.55".cost_to_f   #=> 5425.55

If you are using this method rarely, the best bet is to simply create a function, since adding functions to core classes is not exactly something I would recommend lightly:

def cost_to_f(string)
  string.delete('$,').to_f
end

If you need it in more than one class, you can always put it in a module, then include that module wherever you need it.


One more tidbit. You mentioned that you need to process this string when it is being written to the database. With ActiveRecord, the best way to do this is:

class Item < ActiveRecord::Base
  def price=(p)
    p = p.cost_to_f if p.is_a?(String)  
    write_attribute(:price, p)
  end
end

EDIT: Updated to use String#delete!

wuputah
  • 11,285
  • 1
  • 43
  • 60
3

So many answers... i'll try to summarize all that are available now, before give own answer.

1. string.gsub(/[\$,]/, '')
   string.gsub!(/^\$/, '')
2. string[1..-1]
3. string.slice(0) # => "ome string"
4. s/^.//
  1. Why (g)sub and regexp Just for deleting a character? String#tr is faster and shorter. String#delete is even better.
  2. Good, fast, simple. Power of reverse indexing.
  3. Hm... looks like it returns "S". Because it is an alias to String#[]
  4. Perl? /me is cheking question tags...

And my advice is: What if you have not dollar, but yena? Or what if you don't even have anything before numbers? So i'll prefer:

string[/\d.+/]

This will crop leading non-decimal symbols, that prevent to_f to work well.

P.S.: By the way. It's known, that float is bad practice for storing money amounts. Use Float or Decimal for Accounting Application Dollar Amount?

Community
  • 1
  • 1
Nakilon
  • 34,866
  • 14
  • 107
  • 142
  • gsub() acts like the `/g` modifier of PCRE: s/a/b/ is string.sub(/a/, "b") and s/a/b/g is string.gsub(/a/, "b") in Ruby – polemon Aug 29 '10 at 19:15
  • I know well perl's `s//` and ruby's `gsub`. But question is about ruby. – Nakilon Aug 29 '10 at 19:28
  • What if you have commas in your value? `delete(",$")` is a better solution than our `gsub` though, thanks for pointing that out. Leave a comment next time! – wuputah Aug 30 '10 at 00:51
0

you can use regex for that:

s/^.//

As laways, this is PCRE syntax.

In Ruby, you can use the sub() method of the string class to replace the string:

result = string.sub(/^./,"")

This should work.

[EDIT]

Ok, someone asked what's the gsub() is for:

gsub() acts like sub() but with the /g modifier in PCRE (for global replacement):

s/a/b/

in PCRE is

string.sub(/a/, "b")

and

s/a/b/g

is

string.gsub(/a/, "b")

in Ruby

polemon
  • 4,722
  • 3
  • 37
  • 48
0

You could try something like this.

string = string[1..-1] if string.match(/^\$/)

Or this.

string.gsub!(/^\$/, '')

Remember to put that backslash in your Regexp, it also means "end of string."

AboutRuby
  • 7,936
  • 2
  • 27
  • 20
0

What I'd use (instead of regular expressions) is simply the built-in slice! method in the String class. For example,

s = "Some string"
s.slice!(0) # Deletes and returns the 0th character from the string. 
s # => "ome string"

Documentation here.

sluukkonen
  • 2,566
  • 1
  • 19
  • 12