2009-06-08 5 views
14

Dois-je utiliser if defined?Dans Ruby, devrais-je utiliser || = ou si elle est définie? pour la mémo?

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

Ou ||=

@current_user_session ||= UserSession.find 

J'ai remarqué la méthode if defined? utilisé de plus en plus récemment. Y a-t-il un avantage par rapport à l'autre? Personnellement, je préfère ||= pour la lisibilité. Je pense également que Rails pourrait avoir une macro memoize qui fournit ce comportement de manière transparente. Est-ce le cas?

+0

Il est appelé memoize – nasmorn

Répondre

24

Attention: x || = y assigne x = y si x renvoie false. Cela peut signifier que x est indéfini, nul ou faux.

Il y a plusieurs fois que des variables seront définies et fausses, mais peut-être pas dans le contexte de la variable d'instance @current_user_session.

Si vous désirez concision, essayez la conditionnelle:

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

ou tout simplement:

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

si vous avez juste besoin d'initialiser la variable.

+1

Voulez-vous dire 'défini (@ current_user_session) ou @current_user_session = UserSession? .find' ('ou' au lieu de' || ')? – Jimothy

0

En outre, le ||= plus agréable produit un avertissement (sur 1.8.6 et 1.8.7, au moins) sur les variables d'instance non initialisées, alors que la version plus verbeuse defined? ne le fait pas.

D'autre part, cela ne peut-être ce que vous voulez:

def initialize 
    @foo = nil 
end 

def foo 
    @foo ||= some_long_calculation_for_a_foo 
end 

Mais cela ne certainement pas:

def initialize 
    @foo = nil 
end 

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

depuis toujours @foo se définir à ce moment-là.

+0

tout le point de défini? est de vérifier les variables d'instance non initialisées. – Sam

+0

Egalement, défini? (: @ Foo) TOUJOURS renvoie "expression". Vous vouliez dire défini? (@ Foo). defined (@ foo) renvoie soit nil soit "instance-variable". –

+0

merci pour la prise, Sporkmonger. La faute de frappe est maintenant corrigée. –

1

Rails n'ont memoization, consultez le screencast ci-dessous pour une excellente introduction:

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

Cependant, n'utilisez PAS la memoization de Rails si l'un de vos paramètres est Hashes sauf si vous êtes sur Ruby 1.9. –

+5

'ActiveSupport :: Memoizable' était obsolète dans Rails 3.2. –

+0

@BobAman Je suis sur Ruby 1.9 mais j'ai encore des problèmes quand j'utilise memoization avec des paramètres de hachage. Je suis également sur les rails 3.0 – sjobe

Questions connexes