2014-02-26 4 views
10

In Ruby on Rails, was ist der Unterschied zwischen der Verwendung von Self.attribute und Attribut in einem Modell?Was ist der Unterschied zwischen der Verwendung von selbs.at und Attribut in einem Modell?

In diesem Beispiel sei my_attr ein Attribut des Benutzers, das in der Datenbank gespeichert wird.

class User < ActiveRecord::Base 
    def do_something! 
    self.my_attr = 123 
    end 

    def do_another_thing! 
    my_attr = 456 
    end 
end 
+0

Die Verwendung von 'self' schützt Sie nur vor möglichen Namenskonflikten mit lokalen Variablen gleichen Namens. –

Antwort

9

Der Unterschied ist, dass einer funktioniert, der andere nicht - oder zumindest nicht so, wie Sie es vorhaben.

Ihre zweite Version tut nichts. Es ist nicht gleichbedeutend mit dem Aufruf self.my_attr = 123, sondern es wird einfach eine lokale Variable namens my_attr erstellt und auf 123 gesetzt und dann bei der Rückkehr der Methode wieder gelöscht. Es beeinflusst den my_attr Wert des Modells in keiner Weise.

class User < ActiveRecord::Base 
    def do_another_thing! 
    my_attr = 456 

    puts self.my_attr # nil (or whatever value it was before) 
    end 
end 

Umgekehrt, wenn Sie auf ein Objekt definiert Zugang ein Verfahren möchten, können Sie (und should) auslassen self:

class User 
    def name=(value) 
    @name = value 
    end 

    def name 
    @name 
    end 

    def age=(value) 
    @age = value 
    end 

    def age 
    @age 
    end 

    def do_something 
    self.name = "bob" # self is required 
    puts name # bob 

    age = 47 # @age is unaffected 
    age # nil 
    end 
end 

Beachten Sie, dass dies nicht eine Frage Rails ist, es ist eine Ruby Frage. Es gibt hier keinen Rails-spezifischen Code. Dieses Verhalten ist Teil der Funktionsweise der Ruby-Syntax.

+1

OK, danke. Warum empfiehlst du NICHT, self.name zu verwenden, wenn du einen Namen bekommen willst, sondern self.name zu verwenden, wenn du einen Namen setzen willst? Ich würde denken, dass Sie in beiden Fällen aus Gründen der Konsistenz self.name verwenden möchten. –

+0

@SomeGuy Weil es der [vereinbarte Standard] ist (https://github.com/bbatsov/ruby-style-guide#no-self-unless-required) – meagar

0

do_something! ist eine Instanzmethode. Hier ist das Selbst die Benutzerinstanz, my_attr = ist die Methode Ihrer Benutzerinstanz. Die Funktion besteht darin, der Benutzerinstanzvariablen @may_attr einen Wert zuzuweisen.

In "do_another_thing!" Könnte my_attr eine Variable sein, die Sie gerade deklariert haben.

+0

Das ist nicht wahr. Unter der Annahme, dass die Tabelle 'users' eine' my_attr'-Spalte hat, ist der Effekt von 'self.my_attr = ...' * nicht *, um '@ my_attr' zu setzen. – meagar

0

In diesem Fall gibt es keinen Unterschied. Aber davon ausgehen, dass Sie eine lokale Variable in einer Methodendefinition haben:

def do_something! 
    self.my_attr = 123 
end 

def do_another_thing!(my_attr) 
    puts "my_attr is #{my_attr}" 
    puts "self.my_attr is #{self.my_attr}" 
end 

do_something!   
do_another_thing!(456) 

Dann würde der Ausgang

sein
my_attr is 456 
self.my_attr is 123 

self ein Objekt darstellt. Wenn Sie Methode auf self aufrufen, rufen Sie Methode speziell für das Objekt auf.

4

die allgemeine Regel ist, wenn Sie sich selbst zu modifizieren durch Wert bis zu einem gewissen Attribute zuweisen, verwenden Sie ‚Selbst‘ ausdrücklich

self.first_name = 'Prasad' #if self isnt used, it will create a local variable. 

und wenn Sie dieses Attribut verweisen (aber Modifizierung nicht), verwenden Sie nicht ‚Selbst "

def name 
    name.camelize 
end 

---- ----- UPDATE

wenn wir jedes Attribut zuzugreifen, Rubin prüft, ob Getter (Reader) und Setter (writer) Methoden für dieses Attribut sind d Definiert oder nicht.

Also im obigen Fall (wenn Sie einem Attribut einen Wert zuweisen), greifen Sie nicht direkt auf das Attribut zu, sondern übergeben den Wert an den Setter, der den Wert intern dem Attribut zuweist.

2.1.0p0 :008 > User.first.first_name 
=> "Prasad" 
2.1.0p0 :009 > (User.first.methods - Object.methods).include? :first_name 
=> true 
2.1.0p0 :010 > (User.first.methods - Object.methods).include? :first_name= 
=> true 

Sie können es versuchen, indem sie ein Verfahren zum jedem Modell Zugabe

def some_name 
    first_name = 'Some name' 
    puts self.first_name 
    self.first_name = 'Random Username' 
    puts self.first_name 
end 

und die Konsole neu zu laden und in Ruby

2.1.0p0 :017 > User.first.some_name 
Prasad 
Random Username 
=> nil 
+0

@muistooshort fügte Details zur Antwort hinzu. –

0

Das Schlüsselwort selbst tun können Sie auf den aktuellen Zugriff Objekt - das Objekt, das die aktuelle Nachricht empfängt.

Also self.attribute bezieht sich auf current object's attribute, wo es einfach attribute gibt mit seiner scope.

Lesen Sie diese Anleitung self für weitere Informationen.

Verwandte Themen