2015-09-02 16 views
6

Ich finde mich häufig Ruby-Code schreiben, wo ich auf das Vorhandensein eines Werts überprüfen und anschließend etwas mit diesem Wert tun, wenn es vorhanden ist. Z.B.Etwas tun, wenn Wert vorhanden ist

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

denke ich, es wäre cool, wenn es als

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

Wer weiß, ob es eine solche Funktion in Ruby ist oder wenn Active?

Ich öffnete eine pull request für diese Funktion.

+0

Wenn Sie gerade für einen Einzeiler suchen, könnten Sie einen Inline verwenden if-Anweisung: 'call_something (some_object.some_attribute) wenn some_object.some_attribute.present?' – Sculper

+0

Dies ruft 'some_attribute' zweimal auf, was aus Gründen der Ausführlichkeit und der Performance nicht wünschenswert ist (wenn' some_attribute' IO aufgerufen hat) –

+0

'attr = if some_object. some_attribute.present? call_something (attr) ende dies wird Attribut nur einmal aufrufen –

Antwort

11

Sie können eine Kombination von presence verwenden und try:

Wenn try ohne Argumente aufgerufen wird, um den Empfänger zu einem bestimmten Block ergibt, es sei denn es ist nil:

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

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

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

Ich mag es nicht aus verschiedenen Gründen zu versuchen, aber hier ist es eine gute Antwort auf die Frage. – spickermann

+0

Schön, aber nur, wenn Sie auf Schienen sind – nsave

+0

Wirklich cool - und es scheint, dass Sie "Präsenz" weglassen können und rufen Sie einfach "versuchen" direkt. –

2

könnten Sie versuchen,

do_thing(object.attribute) if object.attribute 

Diese in der Regel in Ordnung ist, es sei denn, das Attribut ein boolean ist. In diesem Fall wird nicht aufgerufen, wenn der Wert falsch ist.

Wenn Ihr Attribut falsch sein kann, verwenden Sie stattdessen .nil?.

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

Ich weiß, aber ich möchte es vermeiden, zweimal auf 'some_object.some_attribute' zu verweisen. –

+0

Wenn das Attribut nicht wirklich eine Methode ist, die schwer belastet wird, dann gibt es sehr wenig Overhead, um es zweimal aufzurufen, es ist ein Stück Daten, das bereits im Speicher gespeichert ist, so dass es schnell ausgeführt werden kann. – AJFaraday

+0

Sie könnten es stattdessen auf eine lokale Variable setzen, obwohl dies für nur zwei Anwendungen nicht viel hilft. Oder Sie könnten den Nil-Check innerhalb Ihrer 'call_something'-Methode hinzufügen, um den aufrufenden Code etwas sauberer zu halten. z.B. 'def call_etwas (attr); zurück wenn attr.nil? ; #Hauptkörper; ende – AJFaraday

0

Obwohl es keine solche Funktionalität gibt, könnte man folgendes tun:

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

Auf der anderen Seite, Rails bietet so viele monkeypatches, daß man zu diesem Zirkus hängen könnte:

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

Warum nicht stattdessen http://guides.rubyonrails.org/active_support_core_extensions.html#try verwenden. Es ist leicht, es ist gut getestet und unterstützt. Vor einigen Jahren haben sie Active Support in kleine Brocken aufgeteilt, so dass wir uns genau das aussuchen können, was wir wollen, und uns darauf verlassen können, dass die AS-Betreuer arbeiten. –

+0

@theTinMan "Versuch" ist eine gute Wahl, ich zeige nur eine Technik, die verwendet werden kann. Ich habe Stefans Antwort aufgefrischt, übrigens. – mudasobwa

Verwandte Themen