Wie extrahiere ich URL-Parameter aus einer URL mit Ruby oder Rails?

137

Ich habe einige URLs, wie

http://www.example.com/something?param1=value1&param2=value2&param3=value3

und ich möchte die Parameter aus diesen URLs extrahieren und sie in einem Hash erhalten. Natürlich könnte ich reguläre Ausdrücke verwenden, aber ich habe mich nur gefragt, ob es einfachere Möglichkeiten gibt, dies mit Ruby oder Rails zu tun. Ich habe im Ruby-Modul nichts gefunden, URIaber vielleicht habe ich etwas verpasst.

Tatsächlich brauche ich eine Methode, die das tun würde:

extract_parameters_from_url("http://www.example.com/something?param1=value1&param2=value2&param3=value3")
#=> {:param1 => 'value1', :param2 => 'value2', :param3 => 'value3'}

Würdest du ein paar Ratschläge haben?

Flackou
quelle
1
Hash[*string.split('&').collect{|i|i.split('=')}.flatten] Dies würde auch funktionieren, aber es ist wahrscheinlich die schlechteste Option für diesen Fall. Trotzdem finden Sie diesen Ausschnitt vielleicht interessant. (Posting als Kommentar, da ich dies nicht als Antwort betrachte :-))
Vojto

Antworten:

162

Ich denke, Sie möchten eine bestimmte URL-Zeichenfolge in einen HASH verwandeln?

Sie können http://www.ruby-doc.org/stdlib/libdoc/cgi/rdoc/classes/CGI.html#M000075 ausprobieren

require 'cgi'

CGI::parse('param1=value1&param2=value2&param3=value3')

kehrt zurück

{"param1"=>["value1"], "param2"=>["value2"], "param3"=>["value3"]}
Scharfschütze
quelle
1
OK, das war der, den ich vermisst habe! Es ist perfekt, wenn es mit URI.parse verwendet wird: CGI.parse (URI.parse (" example.com/… ) gibt den gewünschten Hash zurück. Vielen Dank für Ihre Hilfe.
Flackou
91
Aus Gründen der Klarheit möchte @Flackou Folgendes: CGI.parse(URI.parse(url).query)
Glenn Jackman
Ich habe dies nicht getestet, aber der erste aufgelistete Schlüssel, der die vollständige URL enthält, scheint wirklich falsch zu sein.
Levi
2
Ich musste tatsächlich CGI::parse(URI::parse(url).query)
Folgendes
151

Ich brauchte dasselbe für ein aktuelles Projekt. Aufbauend auf Levis Lösung ist hier eine sauberere und schnellere Methode:

Rack::Utils.parse_nested_query 'param1=value1&param2=value2&param3=value3'
# => {"param1"=>"value1", "param2"=>"value2", "param3"=>"value3"}
Arthur Gunn
quelle
Viel leichter als das Verspotten einer Rack-Anfrage
Gareth
2
Guter Fund. Wenn Sie einfache Parameter (nicht verschachtelt) haben und leistungsabhängig sind, ist Rack :: Utils.parse_query möglicherweise von Interesse. Der Code ist lesenswert: github.com/rack/rack/blob/master/lib/rack/utils.rb
Levi
Vielen Dank, es ist sehr nützlich :)
Blue Smith
Dies funktioniert gut, aber nicht für Kontrollkästchen mit demselben Namen : param1=value1&param1=value2. Der zweite Wert übertrifft den ersten.
B Sieben
Für alle, die nach dem Gegenteil suchen, ist es Rack::Utils.build_nested_query(params)(oder Rack::Utils.build_query(params)wenn es mit analysiert wird Rack::Utils.parse_query).
Zelanix
99

Gerade verbessert mit Levi Antwort oben -

Rack::Utils.parse_query URI("http://example.com?par=hello&par2=bye").query

Bei einer Zeichenfolge wie der obigen URL wird sie zurückgegeben

{ "par" => "hello", "par2" => "bye" } 
rtdp
quelle
7
gute Antwort. Einfach, verarbeitet die vollständige URL wie die Op-Anfragen, und die Ergebniswerte sind Zeichenfolgen anstelle von Arrays, wie in den anderen Antworten. Vielen Dank.
Jackocnr
3
Wie ich oben kommentiert habe, ist es für jeden, der das Gegenteil sucht Rack::Utils.build_query(params).
Zelanix
1
Achtung - nicht ganz umgekehrt, zumindest nicht in Ruby 1.8.7 / Rails 2.3. Eine Abfragezeichenfolge von foo [] = 1 & foo [] = 2 wird korrekt als {"foo" => ["1", "2"]} analysiert, aber build_query wandelt dies in "foo = 1 & foo = 2" um, was beim Analysieren angezeigt wird ergibt wieder {"foo" => "2"}.
Raels
44

Für eine reine Ruby-Lösung kombinieren URI.parsemit CGI.parse(dies kann verwendet werden, auch wenn Rails / Rack usw. nicht erforderlich sind):

CGI.parse(URI.parse(url).query) 
# =>  {"name1" => ["value1"], "name2" => ["value1", "value2", ...] }
alup
quelle
32

Es gibt mehrere Möglichkeiten, um Ihr Problem zu lösen. Andere haben dir einige Tricks gezeigt. Ich kenne einen anderen Trick. Hier ist mein Versuch: -

require 'uri'
url = "http://www.example.com/something?param1=value1&param2=value2&param3=value3"
uri = URI(url)
# => #<URI::HTTP:0x89e4898 URL:http://www.example.com/something?param1=value1&param2=value2&param3=value3>
URI::decode_www_form(uri.query).to_h # if you are in 2.1 or later version of Ruby
# => {"param1"=>"value1", "param2"=>"value2", "param3"=>"value3"}
Hash[URI::decode_www_form(uri.query)] # if you are below 2.1 version of Ruby
# => {"param1"=>"value1", "param2"=>"value2", "param3"=>"value3"}

Lesen Sie die Methodendokumentation von ::decode_www_form.

Arup Rakshit
quelle
13

Schauen Sie sich das adressierbare Juwel an - ein beliebter Ersatz für Rubys URI-Modul, das das Parsen von Abfragen vereinfacht:

require "addressable/uri"
uri = Addressable::URI.parse("http://www.example.com/something?param1=value1&param2=value2&param3=value3")
uri.query_values['param1']
=> 'value1'

(Im Gegensatz zu URI wird anscheinend auch die Parametercodierung / -decodierung behandelt.)

Yarin
quelle
-3

In Ihrem Controller sollten Sie auf ein aufgerufenes Wörterbuch (Hash) zugreifen können params. Wenn Sie also wissen, wie die Namen der einzelnen Abfrageparameter params[:param1]lauten, müssen Sie nur darauf zugreifen. Wenn Sie die Namen der Parameter nicht kennen, können Sie das Wörterbuch durchsuchen und die Schlüssel abrufen.

Einige einfache Beispiele hier .

Kafuchau
quelle
OK, ich wusste das, es funktioniert gut im Controller mit der angeforderten URL, aber wie geht das für andere beliebige URLs?
Flackou