Comment extraire des paramètres d'URL d'une URL avec Ruby ou Rails?

137

J'ai des URL, comme

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

et je voudrais extraire les paramètres de ces URL et les obtenir dans un hachage. Évidemment, je pourrais utiliser des expressions régulières, mais je me demandais simplement s'il y avait des moyens plus simples de le faire avec Ruby ou Rails. Je n'ai rien trouvé dans le module Ruby URImais j'ai peut-être manqué quelque chose.

En fait, j'ai besoin d'une méthode qui ferait cela:

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

Auriez-vous des conseils?

Flackou
la source
1
Hash[*string.split('&').collect{|i|i.split('=')}.flatten] Cela fonctionnerait aussi, mais c'est probablement la pire option pour ce cas. Mais vous pourriez tout de même trouver cet extrait intéressant. (Poster comme commentaire car je ne considère pas cela comme une réponse :-))
Vojto

Réponses:

162

Je pense que vous voulez transformer une chaîne URL donnée en un HASH?

Vous pouvez essayer http://www.ruby-doc.org/stdlib/libdoc/cgi/rdoc/classes/CGI.html#M000075

require 'cgi'

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

Retour

{"param1"=>["value1"], "param2"=>["value2"], "param3"=>["value3"]}
Tireur d'élite
la source
1
OK, c'est celui qui m'a manqué! Il est parfait lorsqu'il est utilisé avec URI.parse: CGI.parse (URI.parse (" example.com/... ) renvoie le hachage souhaité. Merci pour votre aide.
Flackou
91
Pour plus de clarté, @Flackou veut ceci: CGI.parse(URI.parse(url).query)
glenn jackman
Je n'ai pas testé cela, mais la première clé répertoriée, contenant l'URL complète, semble vraiment fausse.
Levi
2
J'ai effectivement dû utiliser ceci: CGI::parse(URI::parse(url).query)
portforwardpodcast
151

J'ai eu besoin de la même chose pour un projet récent. En s'appuyant sur la solution de Levi, voici une méthode plus propre et plus rapide:

Rack::Utils.parse_nested_query 'param1=value1&param2=value2&param3=value3'
# => {"param1"=>"value1", "param2"=>"value2", "param3"=>"value3"}
Arthur Gunn
la source
Beaucoup plus léger que de se moquer d'une demande de rack
Gareth
2
Bonne trouvaille. Si vous avez des paramètres simples (non imbriqués) et que vous êtes sensible aux performances, Rack :: Utils.parse_query peut être intéressant. Le code vaut la peine d'être lu: github.com/rack/rack/blob/master/lib/rack/utils.rb
Levi
Merci, c'est très utile :)
Blue Smith
Cela fonctionne bien , mais ne fonctionne pas pour les cases à cocher avec le même nom: param1=value1&param1=value2. La deuxième valeur l'emporte sur la première.
B Seven
Pour tous ceux qui recherchent l'inverse, c'est Rack::Utils.build_nested_query(params)(ou Rack::Utils.build_query(params)si analysé avec Rack::Utils.parse_query).
zelanix
99

Juste amélioré avec la réponse de Levi ci-dessus -

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

Pour une chaîne comme ci-dessus url, elle retournera

{ "par" => "hello", "par2" => "bye" } 
rtdp
la source
7
très bonne réponse. simple, traite l'URL complète comme le demande l'op, et les valeurs de résultat sont des chaînes au lieu de tableaux, comme dans les autres réponses. Merci.
jackocnr
3
Comme je l'ai commenté ci-dessus, pour ceux qui recherchent l'inverse, c'est Rack::Utils.build_query(params).
zelanix
1
Attention - pas tout à fait l'inverse, du moins pas dans Ruby 1.8.7 / Rails 2.3. Une chaîne de requête de foo [] = 1 & foo [] = 2 est correctement analysée comme {"foo" => ["1", "2"]}, mais build_query la transforme en "foo = 1 & foo = 2", qui une fois analysée renvoie à nouveau {"foo" => "2"}.
Raels
45

Pour une solution Ruby pure, combiner URI.parseavec CGI.parse(cela peut être utilisé même si Rails / Rack etc. ne sont pas nécessaires):

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

Il existe plusieurs façons de résoudre votre problème. D'autres vous ont montré quelques astuces. Je connais un autre truc. Voici mon essai: -

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"}

Lisez la documentation de méthode de ::decode_www_form.

Arup Rakshit
la source
13

Découvrez la gemme adressable - un remplacement populaire du module URI de Ruby qui facilite l'analyse des requêtes:

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

(Il gère également apparemment l'encodage / décodage des paramètres, contrairement à l'URI)

Yarin
la source
-3

Dans votre Controller, vous devriez pouvoir accéder à un dictionnaire (hash) appelé params. Donc, si vous savez quels sont les noms de chaque paramètre de requête, faites simplementparams[:param1] pour y accéder ... Si vous ne savez pas quels sont les noms des paramètres, vous pouvez parcourir le dictionnaire et obtenir les clés.

Quelques exemples simples ici .

kafuchau
la source
OK, je le savais, cela fonctionne bien dans le contrôleur avec l'URL demandée, mais comment faire cela pour d'autres URL arbitraires?
Flackou