2009-06-08 10 views
14

Sollte ich if defined?In Ruby, sollte ich || = verwenden oder wenn definiert? zum Memoisieren?

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

Oder ||=

@current_user_session ||= UserSession.find 

Ich bemerkte die if defined? Methode mehr und mehr vor kurzem verwendet wird. Gibt es einen Vorteil gegenüber dem anderen? Persönlich bevorzuge ich ||= für die Lesbarkeit. Ich denke auch, dass Rails einen memoize Makro haben könnte, der dieses Verhalten transparent bereitstellt. Ist das der Fall?

+0

Es memoize genannt wird – nasmorn

Antwort

24

Vorsicht: x || = y weist x = y zu, wenn x den Wert false zurückgibt. Das kann bedeuten, dass x nicht definiert, null oder falsch ist.

Es gibt viele Variablen, die definiert und falsch sind, aber möglicherweise nicht im Kontext der Instanzvariable @current_user_session.

Wenn Sie Prägnanz wünschen, versuchen Sie das bedingte Konstrukt:

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

oder gerade:

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

, wenn Sie nur die Variable initialisiert werden müssen.

+1

Meinen Sie 'definiert (@ current_user_session) oder @current_user_session = Usersession? .find' ('oder' statt '||')? – Jimothy

0

Zusätzlich erzeugt der nettere ||= eine Warnung (zu 1.8.6 und 1.8.7 zumindest) über nicht initialisierte Instanzvariablen, während die ausführlichere Version defined? dies nicht tut.

Auf der anderen Seite, ist dies wahrscheinlich nicht, was Sie wollen:

def initialize 
    @foo = nil 
end 

def foo 
    @foo ||= some_long_calculation_for_a_foo 
end 

Aber das macht fast schon gar nicht:

def initialize 
    @foo = nil 
end 

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

seit @foo wird immer an diesem Punkt definiert werden.

+0

der ganze Punkt definiert? ist auf nicht initialisierte Instanzvariablen zu prüfen. – Sam

+0

Auch definiert? (: @ Foo) gibt IMMER "Ausdruck" zurück. Du meintest definiert? (@ Foo). definiert? (@ foo) gibt entweder nil oder "instance-variable" zurück. –

+0

danke für den Fang, Sporkmonger. Tippfehler ist jetzt behoben. –

1

Rails tut memoization haben, besuchen Sie das Screencasts unten für eine großartige Einführung:

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

Verwenden Sie Rails Memoization jedoch NICHT, wenn einer Ihrer Parameter Hashes ist, es sei denn, Sie befinden sich in Ruby 1.9. –

+5

'ActiveSupport :: Memoizable' war in Rails 3.2 veraltet. –

+0

@BobAman Ich bin auf Ruby 1.9 aber ich habe immer noch Probleme, wenn ich Memoisierung mit Hash-Parametern verwenden. Ich bin auch auf Schienen 3.0 – sjobe

Verwandte Themen