URI-Handling mit Ruby
von Matthias Reitinger
am 06.03.09 um 00:22 (1669 Hits)
Relativ absolut
ZodiacXP hatte heute das Anliegen, relative URIs in absolute umzuwandeln. Gumbo lieferte wie immer prompt einen hilfreichen Hinweis: ein entsprechender Algorithmus findet sich im RFC 3986. Als Rubyist muss man sich dieses Dokument aber nicht unbedingt zu Gemüte führen, da die Standard-Bibliothek für den Umgang mit URIs passende Klassen bereitstellt.
Das Modul URI
Nachdem man die Bibliothek mit require 'uri' eingebunden hat, kann man auch schon auf das Modul URI zugreifen (in den Beispielen werde ich diese Zeile allerdings weglassen). Module kann man in Ruby als eine Art Namensraum mit Extras verstehen (man kann sie beispielsweise als Mixins verwenden - dazu vielleicht später mal mehr in diesem Blog). Die zwei wichtigsten Methoden möchte ich kurz vorstellen:
URI.parse(uri)
Diese Methode interpretiert den übergebenen String als URI und gibt im Erfolgsfall eine Instanz der Klasse URI::Generic oder einer ihrer spezialisierten Unterklassen zurück. Beispiele für die Unterklassen wären URI::HTTP und URI::FTP für HTTP- bzw. FTP-URIs. Über diese Instanz kann man dann auf die eigenen Bestandteile der URI zugreifen, wie in folgendem...
Beispiel
Auffällig daran: uri.port stand nicht in der URI, wurde aber anhand des Schemas hergeleitet (80 ist der Standard-Port für das HTTP-Protokoll). Nicht vorhandene Teile (hier uri.fragment) liefern nil zurück.Code ruby:
1 2 3 4 5 6 7 uri = URI.parse("http://www.tutorials.de/blog/code-that-sings-3117/") puts uri.class # => URI::HTTP puts uri.scheme # => http puts uri.host # => [url]www.tutorials.de[/url] puts uri.port # => 80 puts uri.path # => [url]http://www.tutorials.de/blog/code-that-sings-3117/[/url] puts uri.fragment # => nil
URI.join(*str)
Ein kleines Beispiel sagt mehr als tausend Worte:
Beispiel
Diese Methode kann also dazu verwendet werden, relative Pfadangaben in absolute URIs umzusetzen (also genau das was ZodiacXP erreichen wollte).Code ruby:
1 2 3 4 5 6 7 8 9 10 11 12 puts URI.join("http://www.tutorials.de/", "blog/") # => [url]http://www.tutorials.de/blog/[/url] puts URI.join("http://www.tutorials.de/", "blog/", "code-that-sings-3117/") # => [url]http://www.tutorials.de/blog/code-that-sings-3117/[/url] puts URI.join("http://www.tutorials.de/blog/code-that-sings-3117/", "/forum/") # => [url]http://www.tutorials.de/forum/[/url] puts URI.join("http://www.tutorials.de/forum/", "programming/") # => [url]http://www.tutorials.de/forum/programming/[/url] puts URI.join("http://www.tutorials.de/forum/programming/", "../cgi-perl-python-ruby/") # => [url]http://www.tutorials.de/forum/cgi-perl-python-ruby/[/url] puts URI.join("http://www.tutorials.de/forum/", "http://www.ruby-lang.org/") # => [url]http://www.ruby-lang.org/[/url]
Instanzmethoden
Die URI-Klassen besitzen einige Instanzmethoden. Auch diese will ich ohne lange Erklärung beispielhaft vorführen:
Beispiel
Code ruby:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 uri = URI.parse("http://www.tutorials.de/blog/code-that-sings-3117/") # URI komponentenweise verändern uri.query = "foo=bar" uri.fragment = "top" puts uri # => [url]http://www.tutorials.de/blog/code-that-sings-3117/?foo=bar#top[/url] # URI erweitern (wie URI.join) puts uri.merge("uri-handling-mit-ruby-983/") # => [url]http://www.tutorials.de/blog/code-that-sings-3117/uri-handling-mit-ruby-983/[/url] puts uri + "uri-handling-mit-ruby-983/" # => [url]http://www.tutorials.de/blog/code-that-sings-3117/uri-handling-mit-ruby-983/[/url] puts uri + "http://www.ruby-lang.org/" # => [url]http://www.ruby-lang.org/[/url] puts uri.absolute? # => true puts uri.relative? # => false puts uri.route_from("http://www.tutorials.de/") # => blog/code-that-sings-3117/?foo=bar#top puts uri.route_from("http://www.tutorials.de/forum/") # => ../blog/code-that-sings-3117/?foo=bar#top puts uri.route_to("http://www.tutorials.de/blog/code-that-sings-3117/uri-handling-mit-ruby-983/") # => uri-handling-mit-ruby-983/
Umwandlung von relativen in absolute URIs
Abschließend zu dieser kleinen Übersicht möchte ich der Vollständigkeit halber noch die Ruby-Lösung zu ZodiacXPs Problem vorstellen:
Was es mit map! auf sich hat, wisst ihr ja schon aus dem Artikel Arbeiten auf Arrays mit Blockparametern.Code ruby:
1 2 3 4 5 6 7 8 9 require 'uri' base = URI.parse("http://www.foo.bar/path/file.ext") paths = ["/folder/th.ing", "this/that.foo", "http://some.where/else"] paths.map! {|path| (base + path).to_s} p paths # => ["http://www.foo.bar/folder/th.ing", "http://www.foo.bar/path/this/that.foo", "http://some.where/else"]
- Matthias






