I have a string called word and a function called infinitive such that
word.infinitive would return another string on some occasions and an empty string otherwise
I am trying to find an elegant ruby one line expression for the code-snippet below
if word.infinitive == ""
return word
else return word.infinitive
Had infinitive returned nil instead of "", I could have done something like
(word.infinitive or word)
But since it does not, I can't take advantage of the short-circuit OR
Ideally I would want
1) a single expression that I could easily embed in other code
2) the function infinitive being called only once
3) to not add any custom gems or plugins into my code
The ActiveSupport presence method converts an empty (or blank?) string to nil. It's designed for your exact use case:
word.infinitive.presence || word
Note that you can easily use ActiveSupport outside of rails:
require 'active_support/core_ext/object/blank'
You can use a regex like this article suggests
(word.infinitive[/.+/m] or word) #Fancy way to convert "" to nil
If you're not ashamed of monkeypatching and abusing syntax, this would work:
class String
def | x
if empty? then x else self end
end
end
Then you can say word.infinitive | word, which actually scans fairly naturally, if you ask me.
However, I think a better idea would be to modify the infinitive method, or add a version of it that returns the word unchanged.
Edit: Here's a possibly more elegant solution:
[word.infinitive, word].find {|x| not x.empty?}
Do the right thing - fix infinitive so that it returns nils instead of blank strings, or wrap it with your own interface if you really can't touch it.
Or you can monkeypatch a new function to String without having to abuse syntax.
class String
def squash
self.empty? ? nil : self
end
end
Now you can do
puts var.squash or "default text"
I'm not a native english speaker so I don't know if squash is the best word. Is there a word that would better convey the idea of "turn into nil only if empty"?
You could use the ternary operator (boolean ? true-val : false-val) with String#empty?
return word.infinitive.empty? ? word : word.infinitive
if you only want to call infinitive once:
return (inf = word.infinitive).empty? ? word : inf
You may also want to consider adding some memoization to your code.
Related
I am currently using capitalize!:
user_input.capitalize!
But, if the input is capitalized, it returns a nil.
I know I can use the method without !, but it will make a copy of the object and pass that instead of changing the object.
user_input.capitalize
How can I use !, but have it work for all cases?
I tried to downcase everything, then capitalize but the same problem exists in some cases.
What is the best way to capitalize all entries?
This is the context:
The user inputs "works", "Works", "WORKS", or "WoRkS"
case 1) user_input = "works"
case 2) user_input = "Works"
case 3) user_input = "WORKS"
case 4) user_input = "WoRkS"
user_input.capitalize! (case 1,3,4 = "Works"; case 2 = nil)
! methods, by convention, modify the receiver and return nil if they make no changes. The safest way to do it is to use two lines:
user_name.capitalize!
user_name
or #tap:
user_name.tap do |s|
s.capitalize!
end
Although, #tap is overkill here.
If all you care about is that the input gets capitalized, use capitalize! and don't worry about the nil.
If you can't have a nil at a certain point in your code (for some reason), don't use capitalize!. Instead do this:
user_input = user_input.capitalize
At the end of the day, either way is fine, idiomatic and will get the input into the state you want it. In and of itself, a nil return value isn't a bad thing - although you may not always want it as a final return value.
Take the String#=~ function for instance. It will return the index of the first match if the match is found, which, as a Fixnum will always act as true in boolean environments. If the match isn't found, it returns null, which acts as false.
Now suppose I have a class:
class A
attr_accessor :myprop
# prints "I am awesome" if #myprop matches /awesome/
# and "I am not awesome" otherwise
def report_on_awesomeness!
puts "I am #{myprop =~ /awesome/ ? 'awesome' : 'not awesome'}."
end
end
This code will pretty much work just as expected, but the first element in the trial conditional operator is the subject of my question.
Is it a good idea not to wrap myprop =~ /awesome/? I'm not talking about abstracting it into another method like def is_awesome?; myprop =~ /awesome/; end but rather whether my current convention, which forces Ruby to implicitly casts Fixnums to true and nils to false, is preferable over wrapping the condition into something I cast myself. I could easily do this:
class A
attr_accessor :myprop
# prints "I am awesome" if #myprop matches /awesome/
# and "I am not awesome" otherwise
def report_on_awesomeness!
puts "I am #{(myprop =~ /awesome/).nil? ? 'not awesome' : 'awesome'}."
end
end
Pros I see for the first style:
Most maintainers (including future me) are used to the implicit type
It's shorter
Pros I see for the second style:
It's more obvious exactly what the relationship is between the result of the =~ method and its boolean interpretation
It gives you more freedom to use more creative explicit casting
I suspect that there might be some middle ground, where you leave implicit type conversions in cases where it's idiomatic (e.g., regular expression matching using =~) and do it explicitly when it's not (e.g., your own properties, especially if they have multiple return types).
I would appreciate any insights or experiences the community can share on this issue.
IMHO that's a personal choice. You can take any style, since you feels better by working with that.
Once I defined true? on Object to get its boolean value (another name could be to_bool):
class Object
def true?
!!self
end
end
But the double bang (!!) is simpler to convert anything to Boolean and I prefer to use it - but not everywhere. I use it only when I need explicity a boolean value (I wouldn't use it in the case of this question).
BTW, false.nil? == false; it could lead to confusion.
probably asked already but I couldn't find it.. here are 2 common situation (for me while programming rails..) that are frustrating to write in ruby:
"a string".match(/abc(.+)abc/)[1]
in this case I get an error because the string doesn't match, therefore the [] operator is called upon nil. What I'd like to find is a nicer alternative to the following:
temp="a string".match(/abc(.+)abc/); temp.nil? ? nil : temp[1]
in brief, if it didn't match simply return nil without the error
The second situation is this one:
var = something.very.long.and.tedious.to.write
var = something.other if var.nil?
In this case I want to assign something to var only if it's not nil, in case it's nil I'll assign something.other..
Any suggestion?
Thanks!
In Ruby on Rails you have the try method available on any Object. According to the API:
Invokes the method identified by the symbol method, passing it any arguments and/or the block specified, just like the regular Ruby Object#send does.
Unlike that method however, a NoMethodError exception will not be raised and nil will be returned instead, if the receiving object is a nil object or NilClass.
So for the first question you can do this:
"a string".match(/abc(.+)abc/).try(:[], 1)
And it will either give you [1] or nil without error.
Forget that Python atavism!
"a string"[/abc(.+)abc/,1] # => nil
"a string"[/abc(.+)abc/, 1]
# => nil
"abc123abc"[/abc(.+)abc/, 1]
# => "123"
And:
var = something.very.long.and.tedious.to.write || something.other
Please note that or has a different operator precedence than || and || should be preferred for this kind of usage. The or operator is for flow control usage, such as ARGV[0] or abort('Missing parameter').
For the first I'd recommend ick's maybe (equivalent to andand)
"a string".match(/abc(.+)abc/).maybe[1]
I am not sure I understand the second one, you want this?
var = something.very.long.and.tedious.to.write || something.other
"a string".match(/foo(bar)/).to_a[1]
NilClass#to_a returns an empty array, and indexing outside of it gives you nil values.
Alternatively (what I do) you can splat the matches:
_, some, more = "a string".match(/foo(bar)(jim)/).to_a
For the first question, I think Bob's answer is good.
For the second question,
var = something.very.long.and.tedious.to.write.instance_eval{nil? ? something.other : self}
I'm trying to figure out how to check if a string matches a regular expression, but I want to know if the entire string matches just once. Here's my code but it seems absurdly long
def single_match(test_me, regex)
ret_val = false
test = regex.match(test_me)
if (test.length==1 && test[0].length == test_me.length)
ret_val = true
end
return ret_val
end
is there an easier way to do this?
P.S. Here's the method I'm really trying to write, since people always seem to ask why I want the gun these days:
def is_int(test_me)
return single_match(test_me, /[0-9]*/)
end
Edit Thanks everybody. Here's where I'm really using it, but this regex stuff is always interesting to go through. Thanks for the great and educational answers.
You don't need to do this, your method can be replaced by using the regular expression of /^[0-9]*$/. The ^ tells it match start of a line and $ tells it match end of the line. So it will match: start of line, 0 to any in range of 0 to 9, and finally end of line.
def is_int(test_me)
test_me =~ /^[0-9]*$/
end
And you don't need the return statements, Ruby implicitly returns the last statement.
Edit:
It probably would be easier and look better to use the to_i instance method of String class.
def is_int(test_me)
test_me.to_i.to_s == test_me
end
Edit: (did some tests)
Comparing the performance between the two methods shows that .to_i.to_s == way is 5% faster. So it is up to personal preference to which ever looks better and if you want to handle leading zeroes.
To do what you really want should be even simpler
def is_int(test_me)
test_me.to_i.to_s == test_me
end
This?
def single_match(str, regex)
str.match(regex).to_s == str
end
To answer your original question, for the sake of people finding this page in a search, "scan" will return an array of matches, so if you want to find out how many times some regexp matches, e.g. how many runs of digits there are, you can do:
mystring.scan(/\d+/).size
I am trying to decide if a string is a number in Ruby. This is my code
whatAmI = "32.3a22"
puts "This is always false " + String(whatAmI.is_a?(Fixnum));
isNum = false;
begin
Float(whatAmI)
isNum = true;
rescue Exception => e
puts "What does Ruby say? " + e
isNum = false;
end
puts isNum
I realize that I can do it with a RegEx, but is there any standard way to do it that I'm missing? I've seen a can_convert? method, but I don't seem to have it.
Is there a way to add a can_convert? method to all Strings? I understand that it's possible in Ruby. I also understand that this may be totally unecessary...
Edit The to_f methods do not work, as they never throw an Exception but rather just return 0 if it doesn't work out.
You've got the right idea. It can be done a little more compactly, though:
isNum = Float(whatAmI) rescue nil
Inlining "rescue" is great fun. Parenthesize the part you're rescuing if you put it in the middle of more stuff, like:
if (isNum = Float(whatAmI) rescue nil) && isNum > 20
...
This might sound overly critical, but based on your description, you're almost certainly doing something "wrong"... Why would you need to check whether a String is a valid representation of a Float but not actually convert the String?
This is just a hunch, but it may be useful to describe what you're trying to accomplish. There's probably a "better" way.
For example, you might want to insert the String into a database and put together an sql statement using string concatenation. It would be preferable to convert to a Float and use prepared statements.
If you just need to inspect the "shape" of the string, it would be preferable to use a regular expression, because, as dylan pointed out, a Float can be represented in any number of ways that may or may not be appropriate.
You may also have to deal with international input, in Europe, a comma is used instead of a period as decimal seperator, yet Ruby Floats have to use the (.).
I don't know about the can_convert method, but generally a class will define methods like to_s, to_i, to_hash and so on. These methods return a different representation of the object, for example, a to_s method will return a string representation of an object.
As for the actual converting, I'm sure someone else can answer that better than me.
On another note, if you're wondering if you can add a method to all strings, you can. Just open up the String class and add it!
class String
def can_convert?
...
end
end
Edit: Strings containing exponential notation are supported by to_f.
>> "6.02e23".to_f
=> 6.02e+23