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?


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

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

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

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", ...] }

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.


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)


-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 .


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.