2012-03-11 51 views
2

在Ruby中是否有.?运算符,它在调用对象之前检查对象是否为nil。? (存在)运营商在红宝石?

举例来说,如果我有代码:

if person and person.neighbor and person.neighbor.house and person.neighbor.house.rooms 
    person.neighbor.house.rooms.each do |room| 
     blah 
    end 
end 

难道还有比其如果检查做一个在任何事情上更好的办法?

请不要说“代码的方式,这些对象不会永远是nil”,我从API调用中获取这些东西,并且无法控制它。

+1

的[得墨忒耳定律(http://en.wikipedia.org/wiki/Law_of_Demeter)可能是有趣的你,因为你的代码侵犯了它严重。 – 2012-03-12 00:05:20

+0

可能重复的[有没有对红宝石Groovy的链式属性的等效零预防?](http://stackoverflow.com/questions/8805582/is-there-an-equivalent-null-prevention-on-chained-attributes在Groovy-in-ruby) – 2012-03-12 00:06:54

+0

@AndrewMarshal,我绝对同意。然而,我想不出一个好的方法来跟踪我的情况下的LoD。我基本上是对第三方认证平台(即facebook twitter等)进行API调用,并获取一个巨大的嵌套信息对象。在这个范围内,我只想抓取一块信息(特别是用户的教育历史),这个信息深深嵌套。除非我写出5种不同的方法,每种方法只能对其后代进行调用,否则我不得不违反LoD。也许有更好的方法? – 2012-03-12 00:12:44

回答

3

最容易做的事情是使用andand宝石,虽然也有一些其他的,很平凡的实施方案,像this,或this,或者等

+1

不知道和和,它很酷的+1 – wintersolutions 2012-03-12 00:06:08

1

你正在寻找的方法是nil?

例子:

foo.nil? 

对于一个更优雅的方式来编程的防守对抗nil值,请参阅我的question关于同一主题。例如,你可以写:

person.neighbor.house.rooms.each do |room| 
    blah 
end 
rescue false 
+0

尽管如此,你不想拯救任意的例外。 – 2012-03-12 00:01:44

+0

@DaveNewton:如果有类似零例外的东西,请随时编辑我的答案 – wintersolutions 2012-03-12 00:04:35

1

对于第二情况下,检查没有对象有方法列表或没有,你可以使用try方法

require "active_support/core_ext/object/try" 
person.try(:neighbor).try(:house).try(:rooms).each do |room| 
    blah 
end 

还是我的try

版本
class Object 
    def try(*args, &block) 
    if args.empty? and block_given? 
     begin 
     instance_eval &block 
     rescue NameError => e 
     puts e.message + ' ' + e.backtrace.first 
     end 
    elsif respond_to?(args.first) 
     send(*args, &block) 
    end 
    end 
end 

然后,你可以做到这一点在短期的方式:

person.try{neighbor.house.rooms}.each do |room| 
    blah 
end 
1

为什么不

begin 
    person.neighbor.house.rooms.each do |room| 
     ... 
    end 
rescue NameError 
    ... 
end 

异常处理程序是为处理异常提出:)所以,如果你依赖别人的代码,你不应该阻止,而是处理你的代码崩溃,而不是检查一切是否正常。

5

从Ruby 2.3.0开始,&.“安全导航”运算符就是这样做的。因此,而不是

person and person.neighbor and person.neighbor.house and person.neighbor.house.rooms

现在你可以只是做

person&.neighbor&.house&.rooms

http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/