rails convert string to number - ruby-on-rails

I am wondering what is a convenient function in Rails to convert a string with a negative sign into a number. e.g. -1005.32
When I use the .to_f method, the number becomes 1005 with the negative sign and decimal part being ignored.

.to_f is the right way.
Example:
irb(main):001:0> "-10".to_f
=> -10.0
irb(main):002:0> "-10.33".to_f
=> -10.33
Maybe your string does not include a regular "-" (dash)? Or is there a space between the dash and the first numeral?
Added:
If you know that your input string is a string version of a floating number, eg, "10.2", then .to_f is the best/simplest way to do the conversion.
If you're not sure of the string's content, then using .to_f will give 0 in the case where you don't have any numbers in the string. It will give various other values depending on your input string too. Eg
irb(main):001:0> "".to_f
=> 0.0
irb(main):002:0> "hi!".to_f
=> 0.0
irb(main):003:0> "4 you!".to_f
=> 4.0
The above .to_f behavior may be just what you want, it depends on your problem case.
Depending on what you want to do in various error cases, you can use Kernel::Float as Mark Rushakoff suggests, since it raises an error when it is not perfectly happy with converting the input string.

You should be using Kernel::Float to convert the number; on invalid input, this will raise an error instead of just "trying" to convert it.
>> "10.5".to_f
=> 10.5
>> "asdf".to_f # do you *really* want a zero for this?
=> 0.0
>> Float("asdf")
ArgumentError: invalid value for Float(): "asdf"
from (irb):11:in `Float'
from (irb):11
>> Float("10.5")
=> 10.5

Related

Parse and convert string to int rails

Hi I'm trying to parse an Xml file to add it to my database.
But one of the field is a string, i mean : "101m" and i wanna convert it to an int to have just 101.
Ty for your help
In ruby, to_i is used to convert objects to integers. Here it is on the console:
>> "101m".to_i
=> 101
>> "101m23".to_i
=> 101
As you can see, .to_i starts from the left and gives up as soon as it finds something that can't be sensibly converted to an integer.

Parse negative currencies with parenthesis

I get the following currencies in an import process:
$22.21
($55.95)
I can do Money.parse('$22.21') to parse into a RubyMoney object.
However, how can I parse ($55.95) into a negative RubyMoney object? Do I need to parse it to a negative number first and then into RubyMoney object? It seems like a common request but I can't find anything via search for some odd reason.
If I get -$55.95, I can then run Money.parse('-$55.95') on it. Bonus points if the method can handle both positive and negative currencies.
from the page that #swapnilabnave linked to:
:negative_format - Sets the format for negative numbers (defaults to prepending an hyphen to the formatted number given by :format). Accepts the same fields than :format, except %n is here the absolute value of the number.
So you would use (%u%n) for the desired effect.
You could do a regex to see if the string includes parenthesis. If it does, remove them, and prepend a negative sign:
str.include?(")") ? str.gsub(/\(|\)/, "").insert(0, "-") : str
Examples:
2.0.0p247 :013 > str = "($55.95)"
=> "($55.95)"
2.0.0p247 :014 > str.include?(")") ? str.gsub(/\(|\)/, "").insert(0, "-") : str
=> "-$55.95"
This works with positive values as well:
2.0.0p247 :016 > str = "$55.95"
=> "$55.95"
2.0.0p247 :017 > str.include?(")") ? str.gsub(/\(|\)/, "").insert(0, "-") : str
=> "$55.95"
First you can delete the parenthesis and then parse
money = "($55.95)"
money = money.delete!('()') and "-#{money}" or money
Money.parse(money)
It's in the readme of RubyMoney sign_before_symbol
Why don't you use number_to_currency ?

Ruby string with USD "money" converted to number

Is there currently a gem that's capable of taking strings, all in USD for this purpose, and converting them to a number? Some examples would be:
"$7,600" would turn into 7600
"5500" would turn into 5500
I know on the "5500" example I can just do "5500".to_i, but the spreadsheets being imported aren't consistent and some include commas and dollar signs while others do not. There a decent way of handling this across the board in Ruby?
I've tried something like money_string.scan(/\d/).join which seems to be fine, just worried I'll run into edge cases I haven't found yet, such as decimal places.
Why not remove all non-digit characters before calling .to_i
Example:
"$7,600".gsub(/\D/,'').to_i
And for a floating point number:
"$7,600.90".gsub(/[^\d\.]/, '').to_f
You can do:
"$100.00".scan(/[.0-9]/).join().to_f
or to_i if they're only dollars
You could use the Money gem
Money.parse("$100") == Money.new(10000, "USD")
You should be able to trim any non-numeric characters with a Ruby RegEx object. Sanitize your inputs to remove anything but numbers to the left of a decimal point, and then parse the numbers-only string as a number.
(And note that, if you're getting actual spreadsheets instead of CSV bunk, there's likely a value property you can read that ignores the text displayed on screen.)
def dollar_to_number(dollarPrice)
if dollarPrice
dollarPrice[1, dollarPrice.length].to_i
end
end
You can use the Monetize gem:
pry(main)> Monetize.parse("$7,600").to_i
=> 7600
https://github.com/RubyMoney/monetize
pry(main)> Monetize.parse("$7,600").class
=> Money
If you are using money-rails gem, you can do the following
irb(main):004:0> "$7,600".to_money("USD")
=> #<Money fractional:760000 currency:USD>
irb(main):005:0> "5500".to_money("USD")
=> #<Money fractional:550000 currency:USD>

Where do I put the option to ignore special characters with Regexp.new?

Here is the code:
def autocomplete
if(params[:terms])
key = params[:terms]
customers = Customer.where(:$or => [
{:first_name => Regexp.new(/^#{key}/i)},
{:last_name => Regexp.new(/^#{key}/i)},
{:email => Regexp.new(/^#{key}/i)},
#{:phone => Regexp.new(/^#{key}[d+]/i)},
{:phone => Regexp.new(/^#{key.gsub(/\D+/,'')}/)},
{:zip_code => key.to_i },
{:street1 => Regexp.new(/#{key}/i)},
{:street2 => Regexp.new(/#{key}/i)}
]
)
The gsub method suggested by Tin Man gets me almost there - it strips any non-Digit characters from the search string only when searching in the :phone field in my DB.
The last problem is that the :phone field in the DB might actually have non-Digits in it (and I want to allow users to enter phone numbers however they want), so I need to temporarily ignore dashes when I'm searching (using find() in Mongo)
Not sure if I should do it at this level in the autocomplete function or if I should do it in the autocomplete.js module...
SUMMARY - I want to :phone.gsub(/\D+/,'') but gsub only works on strings, not a reference like this.
Some things I see:
Regexp.new(/^#{key}[d+]/i)}
[\d+] is nonsense. Drop the surrounding [].
For:
{:zip_code => key.to_i },
Don't convert the zipcode to an integer. Some zip codes are hyphenated, which will drop the trailing value. Also, unless you intend to perform math on the value, leave it as a string.
What is $or? Using a global is usually a sign of code-smell. There are few reasons to use one in Ruby, and I've never found a good use for one in my code, and it's something that can usually be refactored out easily using a constant.
I think you actually answered my question by pointing out the key.to_i for ZIP - that's actually exactly what I WANT to do with Phone Number - strip out all the dashes, spaces, brackets, etc. I am going to give that a try.
No, no, no, no. to_i won't do what you want. '0-1'.to_i => 0 and '0.1'.to_i => 0. Instead you want to strip out all non-numeric characters from the string using gsub, then you're done:
'0.1'.gsub(/\D+/, '')
=> "01"
'123-456-7890'.gsub(/\D+/, '')
=> "1234567890"
'(123) 456 7890'.gsub(/\D+/, '')
=> "1234567890"
'0.1'.gsub(/\D+/, '').to_i
=> 1
Note what happened above when to_i received the "01", the leading zero was removed because it wasn't significant for the representation of an Fixnum. You can force it to display using a string format, but why? A phone number is NOT a numeric value, it's a string value, even though it is a bunch of numbers. We NEVER need to do addition on them, or any math, so it's senseless to convert it to an integer. Keep it as a string of digits.

Length of a unicode string

In my Rails (2.3, Ruby 1.8.7) application, I need to truncate a string to a certain length. the string is unicode, and when running tests in console, such as 'א'.length, I realized that a double length is returned. I would like an encoding-agnostic length, so that the same truncation would be done for a unicode string or a latin1 encoded string.
I've gone over most of the unicode material for Ruby, but am still a little in the dark. How should this problem be tackled?
Rails has an mb_chars method which returns multibyte characters. Try unicode_string.mb_chars.slice(0,50)
"ア".size # 3 in 1.8, 1 in 1.9
puts "ア".scan(/./mu).size # 1 in both 1.8 and 1.9
chars and mb_chars don't give you text elements, which is what you seem to be looking for.
For text elements you'll want the unicode gem.
mb_chars:
>> 'กุ'.mb_chars.size
=> 2
>> 'กุ'.mb_chars.first.to_s
=> "ก"
text_elements:
>> Unicode.text_elements('กุ').size
=> 1
>> Unicode.text_elements('กุ').first
=> "กุ"
You can use something like str.chars.slice(0, 50).join to get the first 50 characters of a string, no matter how many bytes it uses per character.

Resources