2009-06-13 8 views
0

Ich habe eine Autor Klasse:Warum führt Ruby nicht automatisch to_s aus?

class Author < ActiveRecord::Base 
    def to_s 
    name 
    end 
end 

to_s Definition erlaubt es mir puts Author.first zu tun, aber nicht puts Author.first.rjust(10):

NoMethodError: undefined method `rjust' for #<Author:0x21eb5d4> 

Wäre es nicht besser, wenn Rubin automatisch to_s vor der String-Methode versucht, in Fälle wie diese? Gibt es eine Möglichkeit, dieses Verhalten zu erhalten?

Antwort

18

Zunächst einmal, nein, würde es nicht. Ich möchte nicht, dass Ruby einfach sagt "Hey, vielleicht ist das eine String-Methode, lass mich sehen, ob ich es ausführen kann, nachdem ich to_s ausgeführt habe" auf ein beliebiges Objekt. Davon abgesehen, gibt es zwei Lösungen zu dem, was Sie tun möchten:

Wenn Sie sagen wollen „Auf jeden Author Beispiel, wenn jemand eine Methode aufruft, die es nicht hat, aber das String der Fall ist, dann sollte es magisch to_s nennen“, dann tun:

class Author < ActiveRecord::Base 
    def to_s 
    name 
    end 

    def method_missing(s, *a) 
    x = to_s 
    if x.respond_to? s then 
     return x.send(s, *a) 
    else 
     super 
    end 
    end 
end 

Wenn Sie sagen "rjust auf alles, was nicht ein String ist bedeuten sollte to_s erste" nennen, dann:

class Object 
    def rjust(*a) 
    to_s.rjust(*a) 
    end 
end 

(Repe mit anderen Methoden wie gewünscht; Beachten Sie, dass Sie damit Dinge wie 86.rjust(10); ob das eine gute Sache ist oder nicht, kann eine Frage des Geschmacks sein)

+3

Das 'super.method_missing (s, * a)' ist falsch. Es sollte nur "super" sein, was die Version der Superklasse der Methode mit den gleichen Argumenten aufruft. In Ruby verhält sich super wie eine Methode und nicht wie ein Empfänger. – Chuck

+0

@Chuck: Danke, behoben.Ich habe meinen Code vor der Veröffentlichung getestet, wurde aber getäuscht, weil die Aktion "super" eine Ausnahme auslöst - das bedeutet, dass die falsche Syntax in diesem speziellen Fall wie erwartet funktioniert hat. (Da ruby ​​nie versucht, "method_missing" auf den Rückgabewert von super zu nennen) –

2

Wäre es nicht besser, wenn Ruby in solchen Fällen automatisch vor der String-Methode to_s versucht?

Sie fahren einen rutschigen Abhang hinunter, indem Sie nach einer Sprache fragen, "tun Sie einfach, was ich meine (die meiste Zeit)". Während es in vielen Fällen sinnvoll sein könnte, ist es verpflichtet, Dinge an den Rändern zu versauen. In Ihrem Fall, wer ist zu sagen, dass rjust ist keine Methode auf Autor (oder eine seiner Oberklassen) definiert. Eigentlich

1

... gibt es eine Methode, die etwas vage ähnlich wie dies tun würde: to_str

Es ist jedoch immer noch nicht implizit für diesen besonderen Fall genannt werden. Die Existenz einer to_str-Methode in Ruby entspricht effektiv der Aussage: "Jede Methode, die normalerweise einen String als Parameter annehmen würde, kann dieses Objekt implizit in einen String konvertieren, indem sie die Methode to_str aufruft." Die meisten Methoden in der Standardbibliothek versuchen, diese Technik zu verwenden, um String zu erzwingen, und viele Bibliotheken von Drittanbietern tun dies auch.

In dem Beispiel, das Sie angegeben haben, wäre es jedoch absolut unangemessen, wenn Ruby erkennt, dass eine nicht behandelte Nachricht String-ähnlich ist und konvertiert wird. Dies würde zu allen Arten von Fehlern, Bugs und allgemeinem Fehlverhalten in einer Menge von Nicht-String-bezogenem Code führen, insbesondere zu irgendeinem Code wie Builder, der auf dem normalen Verhalten der fehlenden Methode beruht.

Verwandte Themen