Dear friends,
I read a text from VCB. Text can be number or combination of numbers and letters. I wish to change it to length if it is number but before it I need to know is it number or not. Can you help me for it?
@distance = text.to_l
Dear friends,
I read a text from VCB. Text can be number or combination of numbers and letters. I wish to change it to length if it is number but before it I need to know is it number or not. Can you help me for it?
@distance = text.to_l
"a".to_l
#=> Error: #<ArgumentError: Cannot convert "a" to Length>
so …
begin
num = text.to_l
rescue ArgumentError => err
if err.message.start_with?("Cannot convert")
# do something else with text
end
else
@distance = num
end
You can also test strings using a Regexp
(a regular expression.)
In order to be convertible to number, the string must start with numeric characters.
In a regular expression:
\A
matches at the beginning of the string
\s*
matches zero or more whitespace characters
\d+
matches one or more digit characters
… so the expression is:
is_num = /\A\s*\d+/
… and you can test like:
if text !~ is_num
# The text does not start with digits,
# do something else with text
else
@distance = text.to_l
end
But also the String#start_with?
method can also take the regular expression as an argument.
But it’s regular expression doesn’t need the \A
since the method purposefully tests from the start of the string. So you can also do …
if text.start_with?(/\s*\d+/)
@distance = text.to_l
else
# The text does not start with digits,
# do something else with text
end
If you do not wish to allow preceding spaces, then omit the \s*
from the expression.
Your choice.
Dear Dan,
If text for example is 12s, this code cause following error.
Error: #<ArgumentError: Cannot convert “12s” to Length>
I can use “num = text.to_f”. It works if text start by number but no different between 12 and 12s. How can I check text end with “s” or not? Let me know if we have a code like this text.end_with?(“S” || “s”)?
That is the reason why Dan included the other lines of the code… itt will handle the ArgumentError that you get.
http://rubylearning.com/satishtalim/ruby_exceptions.html
Yes you can. And you need to start learning how to look up core Ruby methods on your own.
e.g
def onUserText (text, view)
last_char = text.split("").last
if last_char == "s" || last_char == "S"
@segment = text.to_i
# you can put similar error handling (begin / rescue) check as above
else
#do something else eg. as Dan suggested
begin
num = text.to_l
rescue ArgumentError => err
if err.message.start_with?("Cannot convert")
# do something else with text
end
else
@distance = num
end
end
#.
#.
end
text.end_with?('s','S')
… is far simpler.
Sure! ( I checked the link you have, I just wanted to give an other example…)
Thank you Dezmo, now I know argument error can deleted by codes.
Also following codes solve my problem.
if text.end_with?('s','S') == true
@num = text.to_i
#do something
else
@distance = text.to_f
# do something else
end
… is frivolous. The if
already tests for truthfulness.
Yea. Sure, This methods never raises an exception. Easy!
https://ruby-doc.org/core-2.5.5/String.html#method-i-to_f
Easy?
This will return a normal float. Independent of the current model unit. You have to take care of it in other part of your code.
Thank you Dan, You and Dezmo make my codes beautiful.
I do enjoy your posts. Always teach me something interesting. Thank you.
Avoid comparing the error message text. The API contract states what type the error has but not what the text is. This can be rephrased at any point, or possibly translated.
This would treat the text as being in inches. It fails for models using any other units, when the user specifies a unit, for decimals in countries where a comma is used for decimal symbol, and when using fractions. #to_l is the preferred way to parse text input to a length.
Thank you so much. Also I find this problem and first I should be sure text is number then use text.to_l. In this way I don’t need to be worry about system unit.