2009-06-08 4 views
14

¿Debo usar if defined?En Ruby, ¿debería usar || = o si está definido? para la memorización?

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

O ||=

@current_user_session ||= UserSession.find 

Noté el método if defined? se usa cada vez más recientemente. ¿Hay alguna ventaja para uno sobre el otro? Personalmente, prefiero ||= para la legibilidad. También creo que Rails podría tener una macro memoize que proporciona este comportamiento de forma transparente. ¿Es este el caso?

+0

Se llama memoize – nasmorn

Respuesta

24

Tenga cuidado: x || = y asigna x = y si x devuelve falso. Eso puede significar que x es indefinido, nulo o falso.

Hay muchas veces las variables se definirán y serán falsas, aunque quizás no en el contexto de la variable de instancia @current_user_session.

Si desea concisión, probar el constructor condicional:

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

o simplemente:

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

si sólo necesitas para inicializar la variable.

+1

¿Quieres decir 'definido (@ current_user_session) o @current_user_session = UserSession? .find' ('or' en vez de' || ')? – Jimothy

0

Además, el ||= más agradable produce una advertencia (en 1.8.6 y 1.8.7, al menos) sobre variables de instancia no inicializadas, mientras que la versión más detallada defined? no lo hace.

Por otro lado, esto probablemente hace lo que quiere:

def initialize 
    @foo = nil 
end 

def foo 
    @foo ||= some_long_calculation_for_a_foo 
end 

Pero esto es casi seguro que no:

def initialize 
    @foo = nil 
end 

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

desde @foo se siempre ser definido en ese punto.

+0

todo el punto de definido? es verificar las variables de instancia no inicializadas. – Sam

+0

También, definido? (: @ Foo) SIEMPRE devuelve "expresión". ¿Quiso decir definido? (@ Foo). definido? (@ foo) devuelve nil o "variable de instancia". –

+0

gracias por la captura, Sporkmonger. Typo ahora está arreglado. –

1

Carriles tiene memoization, echa un vistazo a la screencast a continuación para una gran introducción:

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

Sin embargo, NO use la memoria de Rails si alguno de sus parámetros es Hashes a menos que esté en Ruby 1.9. –

+5

'ActiveSupport :: Memoizable' ha quedado obsoleto en Rails 3.2. –

+0

@BobAman Estoy en Ruby 1.9 pero todavía tengo problemas cuando uso la memoria con hash params. También estoy en los rieles 3.0 – sjobe

Cuestiones relacionadas