2009-06-08 10 views
14

Devo usare if defined?In Ruby, dovrei usare || = o se definito? per la memoizzazione?

return @current_user_session if defined?(@current_user_session) 
@current_user_session = UserSession.find 

O ||=

@current_user_session ||= UserSession.find 

ho notato il metodo if defined? essere usato più e più recentemente. C'è qualche vantaggio rispetto all'altro? Personalmente, preferisco lo ||= per la leggibilità. Penso anche che Rails potrebbe avere una macro che fornisce questo comportamento in modo trasparente. È questo il caso?

+0

Si chiama Memoize – nasmorn

risposta

24

Attenzione: x || = y assegna x = y se x restituisce false. Ciò potrebbe significare che x è indefinito, nullo o falso.

Ci sono molte volte le variabili saranno definite e false, anche se forse non nel contesto della variabile di istanza @current_user_session.

Se desideri concisione, provare il costrutto condizionale:

defined?(@current_user_session) ? 
    @current_user_session : @current_user_session = UserSession.find 

o semplicemente:

defined?(@current_user_session) || @current_user_session = UserSession.find 

se avete solo bisogno di inizializzare la variabile.

+1

Vuoi dire 'definito (@ current_user_session) o @current_user_session = UserSession? .find' ('o' invece di' || ')? – Jimothy

0

Inoltre, il più bello ||= produce un avviso (su 1.8.6 e 1.8.7, almeno) sulle variabili di istanza non inizializzate, mentre la versione più verbosa di defined? non lo fa.

D'altra parte, questo probabilmente fa quello che vuoi:

def initialize 
    @foo = nil 
end 

def foo 
    @foo ||= some_long_calculation_for_a_foo 
end 

Ma quasi sicuramente non lo fa:

def initialize 
    @foo = nil 
end 

def foo 
    return @foo if defined?(@foo) 
    @foo = some_long_calculation_for_a_foo 
end 

dal @foo sarà sempre essere definito in quel punto.

+0

l'intero punto definito? è controllare le variabili di istanza non inizializzate. – Sam

+0

Inoltre, definito? (: @ Foo) SEMPRE restituisce "espressione". Intendevi definito? (@ Foo). definito? (@ pippo) restituisce nil o "variabile d'istanza". –

+0

grazie per la presa, Sporkmonger. Typo è ora riparato. –

1

Rails ha Memoizzazione, controlla la screencast sotto per una grande introduzione:

http://railscasts.com/episodes/137-memoization

class Product < ActiveRecord::Base 
    extend ActiveSupport::Memoizable 

    belongs_to :category 

    def filesize(num = 1) 
    # some expensive operation 
    sleep 2 
    12345789 * num 
    end 

    memoize :filesize 
end 
+0

Tuttavia, NON utilizzare la memo razione di Rails se uno qualsiasi dei parametri è Hash, a meno che non si utilizzi Ruby 1.9. –

+5

'ActiveSupport :: Memoizable' è stato deprecato in Rails 3.2. –

+0

@BobAman Sono su Ruby 1.9 ma ho ancora problemi quando uso la memoizzazione con parametri hash. Sono anche su rotaie 3.0 – sjobe