2010-07-26 9 views

Antwort

65

send sendet eine Nachricht an eine Objektinstanz und seine Vorfahren in der Klassenhierarchie, bis ein Verfahren reagiert (da der Name das erste Argument übereinstimmt).

Praktisch sind diese Linien äquivalent:

1.send '+', 2 
1.+(2) 
1 + 2 

Beachten Sie, dass send Sichtbarkeitsprüfungen umgeht, so dass Sie private Methoden aufrufen können, auch (nützlich für die Testeinheit).


Wenn es vor dem Senden wirklich keine Variable ist, bedeutet dies, dass das globale Objekt verwendet wird:

send :to_s # "main" 
send :class # Object 
+0

Oh ich sehe, also könnte man senden, wenn man etwas wie 1.Monat in der Datenbank speichern möchte, anstatt statisch die Anzahl der Tage anzugeben. –

+2

Wahr, Sie könnten es verwenden, um Methoden mit Namen aufzurufen, die berechnet werden, nicht statisch. (Sie sollten jedoch keine uneingeschränkte Benutzereingabe zulassen, um den Aufruf von privaten Methoden zu vermeiden ... Sie könnten ihnen jedoch ein eindeutiges Präfix geben: send 'user_method _' + Methodenname, * args) – giraff

+0

Guter Anwendungsfall könnte es sein, den Sie wollen Um eine geschützte Klassenmethode zu testen, könnten Sie sie außerhalb einer Class-In-Testdatei aufrufen. –

69

senden ist eine Ruby (ohne Rails) -Methode, die es erlaubt, eine andere Methode namentlich aufzurufen.

Von Dokumentation

class Klass 
    def hello(*args) 
     "Hello " + args.join(' ') 
    end 
    end 
    k = Klass.new 
    k.send :hello, "gentle", "readers" #=> "Hello gentle readers" 

http://corelib.rubyonrails.org/classes/Object.html#M001077

+3

Große Antwort, klarer als die ausführliche angenommene Antwort. –

33

Eines der nützlichsten Feature, das ich mit .send Methode denken, ist, dass es dynamisch aufrufen auf Methode. Dies kann Ihnen viel Tipparbeit ersparen. Eine der beliebtesten Anwendungen der .send-Methode ist die dynamische Zuweisung von Attributen. Zum Beispiel:

class Car 
    attr_accessor :make, :model, :year 
end 

Um Attribute zuweisen regelmäßig möchte man

brauchen
c = Car.new 
c.make="Honda" 
c.model="CRV" 
c.year="2014" 

Oder mit .send Methode:

c.send("make=", "Honda") 
c.send("model=", "CRV") 
c.send("year=","2014") 

Aber es kann alles mit folgenden Fassung:

Angenommen, Ihre Rails-App muss Ihrer Benutzerklasse Attribute aus Benutzereingaben zuweisen, yo u kann

c = Car.new() 
params.each do |key, value| 
    c.send("#{key}=", value) 
end 
+0

Vielen Dank für den tollen Link –

+3

Die Verwendung von .send auf diese Weise fügt unnötige Komplexität hinzu und macht es einfacher, versehentlich einen Fehler in den Code einzuführen. Wenn Sie beispielsweise in Ihrem obigen Code einen neuen Eintrag zu Ihrem Parameter-Hash hinzufügen (z. B. "cylinders"), schlägt der Code mit einem nicht definierten Methodenfehler fehl. –

+1

antwort_to? könnte verwendet werden, um solche Fehler zu verhindern, falls gewünscht. –

8

Ein weiteres Beispiel, ähnlich wie Antonio Jha das tun https://stackoverflow.com/a/26193804/1897857

ist, wenn Sie Attribute für ein Objekt lesen müssen.

Zum Beispiel, wenn Sie ein Array von Zeichenfolgen haben, wenn Sie versuchen, durch sie zu durchlaufen und sie auf Ihrem Objekt aufrufen, wird es nicht funktionieren.

atts = ['name', 'description'] 
@project = Project.first 
atts.each do |a| 
    puts @project.a 
end 
# => NoMethodError: undefined method `a' 

Sie können jedoch die Saiten zum Objekt send:

atts = ['name', 'description'] 
@project = Project.first 
atts.each do |a| 
    puts @project.send(a) 
end 
# => Vandalay Project 
# => A very important project 
+0

Danke für die einfache und einfache Erklärung! –

+0

Danke! Das ist genau die Antwort, nach der ich suche. Fragen Sie sich, ob das häufig verwendet wird? Ich bin im Legacy-Code auf etwas Ähnliches gestoßen, nicht sicher, dass ich dabei bleiben sollte. @ Mike Vallano –

+0

@ b-liu Ich habe es von erfahrenen Entwicklern in neuem Code verwendet gesehen. Es kann auch hilfreich sein, wenn Sie 'define_method' verwenden: https://apidock.com/ruby/Module/define_method. –

0

Ein weiterer Anwendungsfall für Ansichten:

<%= link_to 
    send("first_part_of_path_{some_dynamic_parameters}_end_path", 
    attr1, attr2), .... 
    %> 

zulassen. Sie schreiben skalierbare Ansicht, wer mit allen Arten von Objekten arbeiten mit: