Bücher online kostenlos Kostenlos Online Lesen
Die Programmiersprache Ruby (German Edition)

Die Programmiersprache Ruby (German Edition)

Titel: Die Programmiersprache Ruby (German Edition) Kostenlos Bücher Online Lesen
Autoren: David Flanagan , Yukihiro Matsumoto
Vom Netzwerk:
Singleton-
     # Methode definiert. Und \#{} wird interpoliert, wenn die
     # Singleton-Methode aufgerufen wird.
     eigenclass.class_eval %Q{
     def #{m}(*args, &block)
     begin
     STDERR << "Eintritt: #{m}(\#{args.join(', ')})\n"
     result = super
     STDERR << "Ausgang: #{m} with \#{result}\n"
     result
     rescue
     STDERR << "Abbruch: #{m}: \#{$!.class}: \#{$!.message}"
     raise
     end
     end
     }
    end
end
# Tracing der angegebenen oder aller Methoden beenden
def untrace!(*methods)
    # Wenn keine Methoden angegeben wurden, das
    # Tracing aller zurzeit überwachten Methoden beenden
    if methods.size == 0
     methods = @_traced
     STDERR <<
     "Beende Tracing aller Methoden für #{object_id}\n"
    else # Andernfalls Tracing aufheben
     methods.map! {|m| m.to_sym } # Strings für alle angegebenen Tracing-Methoden in
     # Symbole konvertieren
     methods &= @_traced
     STDERR <<
     "Beende Tracing von #{methods.join(', ')} für #{object_id}\n"
    end
    # Aus der Menge der Tracing-Methoden entfernen
    @_traced -= methods
    # Tracing-Singleton-Methoden aus der Eigenclass entfernen
    # Beachten Sie, dass class_eval hier einen Block und keinen String
    # auswertet.
    (class << self; self; end).class_eval do
     methods.each do |m|
     # undef_method würde nicht korrekt funktionieren.
     remove_method m
     end
    end
    # Wenn kein Methoden-Tracing mehr stattfindet, unsere Instanz-
    # variable entfernen
    if @_traced.empty?
     remove_instance_variable :@_traced
    end
end
end
    Listing 8.10 Chaining mit Singleton-Methoden für Tracing

8.12 Domänenspezifische Sprachen
    Der Zweck der Metaprogrammierung in Ruby besteht oft in der Erzeugung domänenspezifischer Sprachen ( domain-specific languages oder DSLs ). Eine DSL ist einfach eine Erweiterung der Ruby-Syntax (durch Methoden, die wie Schlüsselwörter aussehen) oder eine API, die Ihnen ermöglicht, auf natürlichere Weise ein Problem zu lösen oder Daten darzustellen, als es anderweitig möglich wäre. Für unsere Beispiele betrachten wir die Ausgabe formatierter XML-Daten als Problemdomäne und definieren zwei DSLs — eine sehr einfache und eine klügere — um dieses Problem anzugehen. [ 31 ]
    8.12.1 Einfache XML-Ausgabe mit method_missing
    Wir beginnen mit einer einfachen Klasse namens
XML
zur Erzeugung einer XML-Ausgabe. Hier sehen Sie ein Beispiel dafür, wie
XML
eingesetzt werden kann:
pagetitle = "Testseite für XML.generate"
XML.generate(STDOUT) do
html do
    head do
     title { pagetitle }
     comment "Dies ist ein Test."
    end
    body do
     h1(:style => "font-family:sans-serif") { pagetitle }
     ul :type=>"square" do
     li { Time.now }
     li { RUBY_VERSION }
     end
    end
end
end
    Das sieht nicht aus wie XML, sondern irgendwie wie Ruby. Hier die Ausgabe, die es erzeugt (mit einigen Zeilenumbrüchen, die für die Lesbarkeit hinzugefügt wurden):

Testseite für XML.generate


Testseite für XML.generate



    Um diese Klasse und die von ihr unterstützte XML-Erzeugungssyntax zu implementieren, verlassen wir uns auf
    Rubys Blockstruktur,
Rubys Methodenaufrufe mit optionalen Klammern,
Rubys Syntax zur Übergabe von Hash-Literalen ohne geschweifte Klammern an Methoden und
Die Methode
method_missing
.
    Listing 8.11 zeigt die Implementierung dieser einfachen DSL.
    class XML
# Eine Instanz dieser Klasse erzeugen, unter Angabe eines Stream
# oder eines Objekts für die Ausgabe. Das kann jedes Objekt sein,
# das auf <<(String) reagiert.
def initialize(out)
    @out = out # Merken, wohin unsere Ausgabe gesendet wird
end
# Das angegebene Objekt als CDATA ausgeben, nil zurückgeben
def content(text)
    @out << text.to_s
    nil
end
# Ausgabe des Objekts als Kommentar, nil zurückgeben
def comment(text)
    @out << ""
    nil
end
# Ein Tag mit dem angegebenen Namen und den angegebenen
# Attributen ausgeben. Wenn ein Block vorhanden ist, wird er
# aufgerufen, um Inhalte auszugeben oder zurückzugeben.
# nil zurückgeben
def tag(tagname, attributes={})
    # Ausgabe des Tag-Namens
    @out << "<#{tagname}"
    # Ausgabe der Attribute
    attributes.each {|attr,value| @out << " #{attr}='#{value}'" }

    if block_given?
     # Dieser Block besitzt Inhalte.
     @out << '>' # Ende des öffnenden Tags
     # Block aufrufen, um Inhalte auszugeben oder zurückzugeben
     content = yield
     if content # Wenn Inhalte zurückgegeben werden
     @out << content.to_s #

Weitere Kostenlose Bücher