2015-09-02 52 views
6

我经常发现自己正在编写Ruby代码,在该代码中检查值的存在并随后使用该值执行某些操作(如果存在该值)。例如。如果存在值,请执行某些操作

if some_object.some_attribute.present? 
    call_something(some_object.some_attribute) 
end 

,我认为它会很酷,如果可以写成

some_object.some_attribute.presence { |val| call_something(val) } 
=> the return value of call_something 

任何人都知道,如果有在Ruby或者虽然是的ActiveSupport这样的功能?

我为此功能打开了一个pull request

+0

如果你只是在寻找一个班轮,你可以使用内联if语句:'call_something(some_object.some_attribute)if some_object.some_attribute.present?' – Sculper

+0

这会调用'some_attribute'两次,这对于冗长和性能的原因是不可取的(如果'some_attribute'调用IO) –

+0

'attr = if some_object。 some_attribute.present? call_something(attr) end'这将只调用属性一次 –

回答

11

您可以使用presencetry组合:

如果try是不带参数调用它产生的接收器给定块的,除非它是nil

'foo'.presence.try(&:upcase) 
#=> "FOO" 

' '.presence.try(&:upcase) 
#=> nil 

nil.presence.try(&:upcase) 
#=> nil 
+0

我不喜欢'尝试'由于各种原因,但这里是一个很好的答案。 – spickermann

+0

不错,但只有当你在轨道上 – nsave

+0

真的很酷 - 看来你可以省略'presence'并直接调用'try'。 –

2

你可以尝试

do_thing(object.attribute) if object.attribute 

这通常是罚款,除非该属性是一个布尔值。在这种情况下,如果该值为假,则不会调用。

如果您的属性可能为false,请改为使用.nil?

do_thing(object.attribute) unless object.attribute.nil? 
+0

我知道,但我想避免两次提到'some_object.some_attribute'。 –

+0

除非该属性实际上是一个正在做一些繁重工作的方法,否则调用它两次的开销非常小,这是一块已经存储在内存中的数据,因此执行起来很快。 – AJFaraday

+0

您可以将其设置为局部变量,但这对于仅两种用法确实没有多大帮助。或者你可以在你的'call_something'方法中添加零检查,保持调用代码更清洁。例如'def call_something(attr);如果attr.nil返回? ; #主体;结束' – AJFaraday

0

尽管没有这种功能,但可以这样做:

some_object.some_attribute.tap do |attr| 
    attr.present? && call_smth(attr) 
end 

在另一方面,Rails提供这么多monkeypatches,一个可以附加一个该马戏团:

class Object 
    def presense_with_rails 
    raise 'Block required' unless block_given? 
    yield self if self.present? # requires rails 
    end 
    def presense_without_rails 
    raise 'Block required' unless block_given? 
    skip = case self 
      when NilClass, FalseClass then true 
      when String, Array then empty? 
      else false 
      end 
    yield self unless skip 
    end 
end 
+0

为什么不改用http://guides.rubyonrails.org/active_support_core_extensions.html#try。它重量轻,经过充分测试和支持。多年前,他们将Active Support分解为小块,因此我们可以挑选我们想要的东西,并可以依靠AS维护人员保持它的工作。 –

+0

@theTinMan'try'是一个不错的选择,我只是展示了一种可以使用的技术。顺便提一下Stefan的回答。 – mudasobwa

相关问题