Analysieren Sie einen String so, als wäre er ein Querystring in Ruby on Rails

78

Ich habe eine Zeichenfolge wie diese:

"foo=bar&bar=foo&hello=hi"

Bietet Ruby on Rails Methoden, um dies so zu analysieren, als wäre es ein Querystring, sodass ich einen Hash wie diesen erhalte:

{
    :foo => "bar",
    :bar => "foo",
    :hello => "hi"
}

Oder muss ich es selbst schreiben?

BEARBEITEN

Bitte beachten Sie, dass die obige Zeichenfolge keine echte Abfrage einer URL ist, sondern eine Zeichenfolge, die in einem Cookie von Facebook Connect gespeichert ist.

Julik
quelle

Antworten:

163

Die Antwort hängt von der verwendeten Rails-Version ab. Wenn Sie 2.3 oder höher verwenden, verwenden Sie den integrierten Parser von Rack für Parameter

 Rack::Utils.parse_nested_query("a=2") #=> {"a" => "2"}

Wenn Sie auf älteren Schienen sind, können Sie in der Tat verwenden CGI::parse. Beachten Sie, dass sich die Handhabung von Hashes und Arrays zwischen den Modulen geringfügig unterscheidet. Sie müssen daher überprüfen, ob die erhaltenen Daten für die von Ihnen ausgewählte Methode korrekt sind.

Sie können auch Rack::Utilsfür den Kurzzugriff in Ihre Klasse aufnehmen.

Julik
quelle
Wenn Sie ein params-Objekt erhalten möchten, wie es Rails für Sie bereitstellt, können Sie dies tun: params = ActionController :: Parameters.new (Rack :: Utils.parse_nested_query ("a = 2"))
adailey
Weiß jemand, ob es möglich ist, zu vermeiden, dass die Parameterwerte der Abfragezeichenfolge in Zeichenfolgen umgewandelt werden? Beispiel: Ich möchte dieses Verhalten: `` `Rack :: Utils.raw_parse_nested_query (" a = 2 ") # => {" a "=> 2}` ``
mecampbellsoup
1
Während dies die meiste Zeit schön ist: Es analysiert "a[]=&a[]=z"als {"a[]"=>["", "z"]}, wobei jeder Parser tatsächlich von ActionController::BaseRetouren verwendet wird{:a => ["z"]}
Jeremy List
36

Das

CGI::parse("foo=bar&bar=foo&hello=hi")

Gibt Ihnen

{"foo"=>["bar"], "hello"=>["hi"], "bar"=>["foo"]}
dombesz
quelle
2
Dies ist die einzige Implementierung, die ich ausprobiert habe und die mehrere Instanzen jedes Parameters verarbeitet - Danke!
Ryan Long
7
Das Problem ist, dass die meisten Leute keine Arrays wollen und eine einfache Schlüssel =>
Wertantwort
12

Bearbeiten: Wie in den Kommentaren erwähnt, kann das Symolisieren von Schlüsseln Ihren Server herunterfahren, wenn jemand Sie verletzen möchte. Ich mache es immer noch oft, wenn ich an Low-Profile-Apps arbeite, weil es die Arbeit erleichtert, aber ich würde es für High-Stake-Apps nicht mehr tun

Vergessen Sie nicht, die Schlüssel zu symbolisieren, um das gewünschte Ergebnis zu erzielen

Rack::Utils.parse_nested_query("a=2&b=tralalala").deep_symbolize_keys

Diese Operation ist für Duplikate destruktiv.

systho
quelle
8
Das Symbolisieren von vom Benutzer bereitgestellten Schlüsseln ist eine schlechte Idee. Symbole werden nicht GC. Wenn also jemand Ihren Server mit vielen falschen Parameterschlüsseln spammt, wird der Prozessspeicher irgendwann erschöpft.
Julik
6
Ruby 2.2 wird jetzt GC-Symbole.
Lesleh
8

Wenn Sie über die URLs sprechen, die verwendet werden, um Daten über die Parameter abzurufen

> request.url
=> "http://localhost:3000/restaurants/lokesh-dhaba?data=some&more=thisIsMore"

Dann, um die Abfrageparameter zu erhalten. verwenden

> request.query_parameters
=> {"data"=>"some", "more"=>"thisIsMore"}
lokeshjain2008
quelle
1

Wenn Sie einen Hash möchten, können Sie verwenden

Hash[CGI::parse(x).map{|k,v| [k, v.first]}]
Arnold Roa
quelle
5
CGI.parse(query).transform_values(&:first)
Chocolateboy