开发者

ruby syntactic sugar: dealing with nils

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".matc开发者_StackOverflowh(/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}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜