2015-09-02 38 views
6

Mi trovo spesso a scrivere codice Ruby dove controllo la presenza di un valore e successivamente faccio qualcosa con quel valore se è presente. Per esempio.Fai qualcosa se il valore è presente

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

Penso che sarebbe bello, se potesse essere scritto come

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

Qualcuno sa se c'è una tale funzione in Ruby o se ActiveSupport?

Ho aperto un pull request per questa funzione.

+0

Se siete solo in cerca di una battuta, si potrebbe usare un inline if statement: 'call_something (some_object.some_attribute) if some_object.some_attribute.present?' – Sculper

+0

Questo richiama 'some_attribute' due volte, cosa non desiderabile per verbosità e motivi di prestazione (se' some_attribute' ha invocato IO) –

+0

'attr = if some_object. some_attribute.present? call_something (attr) end' questo chiamerà attributo solo una volta –

risposta

11

È possibile utilizzare una combinazione di presence e try:

Se try viene chiamato senza argomenti cede il ricevitore ad un dato blocco a meno che sia nil:

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

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

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

Non mi piace provare per vari motivi, ma qui è un'ottima risposta alla domanda. – spickermann

+0

Bello ma solo se sei su rotaie – nsave

+0

Davvero bello - e sembra che tu possa omettere la presenza e invocare direttamente 'try'. –

2

Si potrebbe provare

do_thing(object.attribute) if object.attribute 

Questo è di solito bene, a meno che l'attributo è un valore booleano. Nel qual caso non chiamerà se il valore è falso.

Se l'attributo può essere falso, utilizzare invece .nil?.

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

Lo so, ma voglio evitare di riferire 'some_object.some_attribute' due volte. –

+0

A meno che l'attributo non sia in realtà un metodo che sta facendo un po 'di sollievo, c'è poco overhead nel chiamarlo due volte, è un pezzo di dati che è già memorizzato, quindi è veloce da eseguire. – AJFaraday

+0

Puoi invece impostarlo su una variabile locale, sebbene questo non sia di grande aiuto per soli due utilizzi. Oppure puoi aggiungere il controllo nullo all'interno del metodo 'call_something', mantenendo il codice chiamante un po 'più pulito. per esempio. 'def call_something (attr); ritorno se attr.nil? ; #corpo principale; fine' – AJFaraday

0

Anche se non esiste questa funzionalità, è possibile:

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

D'altra parte, Rails offre così tante monkeypatches, che si potrebbe aggiungere uno a questo circo:

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

Perché non utilizzare invece http://guides.rubyonrails.org/active_support_core_extensions.html#try. È leggero, è ben testato e supportato. Anni fa hanno rotto l'Active Support in piccoli blocchi, così da poter scegliere ciò che vogliamo e possiamo contare sui manutentori di AS per mantenerlo attivo. –

+0

@theTinMan 'try' è una buona scelta, ho solo una tecnica che può essere usata. Ho svalutato la risposta di Stefan, btw. – mudasobwa

Problemi correlati