2016-05-05 9 views
0

Also, das ist ziemlich klar in Javascript, die selbst wäre in dieser Situation, aber ich bin nicht positiv in Ruby.Wer ist "selbst" in einem Ruby-Klassenblock?

class Product 

    after_initialize do |p| 
    p.set_approved 
    end 

    set_approved 
    approved = true 
    end 
end 

Weil ich war ziemlich sicher, dass p wäre, da ich den Code bin sicher,

def after_initialize(&blk) 
    yield(self) 
end 

eine Art ist und der Kontext der beiden Methoden ist self, warum ich zu tun

tun haben
def set_approved(p) 
    p.approved = true 
end 
+1

In Ruby bezieht sich 'self' fast immer auf die Objektinstanz oder den Klassenkontext, in dem die Methode definiert ist. Wo existiert' a_i'? Ist das Ihre Kurzform für 'after_initialize'? Versuchen Sie, das nicht in Fragen zu tun. – tadman

+0

@sawa 'self' kann (normalerweise) in Ruby beim Aufruf von Methoden angegeben werden. Also in diesem Fall genehmigt ist eine db-Spalte und automatisch von Rails erstellt. – MCB

+0

Ich vermisste die, die du in 'yield (self) 'hast. – sawa

Antwort

3

In Ruby self ist viel mehr gesperrt und vorhersagbar als this ist in JavaScript. Sie müssen wirklich aus dem Weg gehen, um die Bindung eines Blocks zu wechseln, und wenn Sie das tun, können Sie Leute überraschen, was zu Verwirrung führt, so dass es normalerweise vermieden wird.

Hier ist, was tatsächlich passiert ist und wie man es neben Schritt, wenn es nicht wünschenswert ist:

class Product 
    # Usage type #1: Supply a Proc 
    after_initialize do |p| 
    # self here refers to the Product class since this block was defined at the 
    # class level. 
    p.set_approved 
    end 

    # Usage type #2: Call a method 
    after_initialize :trigger_set_approved 

protected 
    def trigger_set_approved 
    # This is an instance method, so self is an instance of Product 
    self.set_approved 
    end 
end 

Rebinding den Block zu after_initialize gegeben schädlichen Auswirkungen haben könnte, so ist es normalerweise nicht getan. Wenn Sie eine Klassenmethode aufrufen möchten, die dort definiert ist, müssen Sie self.class.class_method_name anstelle von class_method_name aufrufen.

Mit anderen Worten, es wird erwartet, dass der Ausführungskontext des Blocks unter normalen Umständen nicht umgeschaltet wird.

+0

Ja, also 'after_initialize' ist eine class_method, also warum nicht' self' in 'set_approved 'beziehen Sie sich auf die Instanz' p', von der es aufgerufen wurde. Und jede Idee, wie sie "Produkt" für die Instanz, die gerade initialisiert wurde, anstatt für die Klasse, in der sie erstellt wurde, "selbst" gemacht haben? – MCB

+0

Wenn Sie 'set_approved' als Instanzmethode definiert haben, brauchen Sie das' p' Argument nicht, es wird 'self' sein. – tadman