Jak wyodrębnić parametry URL z adresu URL za pomocą Ruby lub Rails?

137

Mam kilka adresów URL, na przykład

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

i chciałbym wyodrębnić parametry z tych adresów URL i uzyskać je w skrócie. Oczywiście mogłem używać wyrażeń regularnych, ale zastanawiałem się tylko, czy istnieje prostszy sposób na zrobienie tego z Rubim lub Railsami. Nie znalazłem nic w module Ruby, URIale może coś przeoczyłem.

Właściwie potrzebuję metody, która by to zrobiła:

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

Czy masz jakieś rady?

Flackou
źródło
1
Hash[*string.split('&').collect{|i|i.split('=')}.flatten] To też by działało, ale to prawdopodobnie najgorsza opcja w tym przypadku. Ale nadal możesz uznać ten fragment za interesujący. (Publikowanie jako komentarz, ponieważ nie uważam tego za odpowiedź :-))
Vojto

Odpowiedzi:

162

Myślę, że chcesz zamienić dowolny ciąg adresu URL w HASH?

Możesz spróbować http://www.ruby-doc.org/stdlib/libdoc/cgi/rdoc/classes/CGI.html#M000075

require 'cgi'

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

zwroty

{"param1"=>["value1"], "param2"=>["value2"], "param3"=>["value3"]}
Snajper
źródło
1
OK, to był ten, którego przegapiłem! Jest to idealne rozwiązanie w przypadku korzystania z URI.parse: CGI.parse (URI.parse (” example.com/... ) zwraca żądaną Hash Dzięki za pomoc..
Flackou
91
Dla jasności @Flackou chce tego: CGI.parse(URI.parse(url).query)
glenn jackman
Nie testowałem tego, ale pierwszy wymieniony klucz, zawierający pełny adres URL, wydaje się naprawdę zły.
Levi
2
Właściwie musiałem tego użyć: CGI::parse(URI::parse(url).query)
portforwardpodcast
151

Okazało się, że potrzebuję tego samego w przypadku niedawnego projektu. Opierając się na rozwiązaniu Levi's, oto czystsza i szybsza metoda:

Rack::Utils.parse_nested_query 'param1=value1&param2=value2&param3=value3'
# => {"param1"=>"value1", "param2"=>"value2", "param3"=>"value3"}
Arthur Gunn
źródło
O wiele lżejszy niż kpienie z żądania Rack
Gareth
2
Dobre znalezisko. Jeśli masz proste parametry (niezagnieżdżone) i zależy Ci na wydajności, Rack :: Utils.parse_query może być interesujący. Kod warto przeczytać: github.com/rack/rack/blob/master/lib/rack/utils.rb
Levi
Dziękuję, to bardzo przydatne :)
Blue Smith
Działa to dobrze, ale nie działa dla wyboru o tej samej nazwie: param1=value1&param1=value2. Druga wartość jest ważniejsza od pierwszej.
B Seven
Dla każdego, kto szuka odwrotności, jest Rack::Utils.build_nested_query(params)(lub Rack::Utils.build_query(params)jeśli zostanie przeanalizowany Rack::Utils.parse_query).
zelanix
99

Just Improved dzięki powyższej odpowiedzi Levi -

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

W przypadku ciągu, takiego jak powyższy adres URL, zwróci

{ "par" => "hello", "par2" => "bye" } 
rtdp
źródło
7
świetna odpowiedź. proste, przetwarza pełny adres URL tak, jak pyta operacja, a wartości wynikowe są ciągami znaków zamiast tablicami, jak w innych odpowiedziach. dzięki.
jackocnr
3
Jak skomentowałem powyżej, dla każdego, kto szuka odwrotności, to jest Rack::Utils.build_query(params).
zelanix
1
Uwaga - nie do końca na odwrót, przynajmniej nie w Ruby 1.8.7 / Rails 2.3. Ciąg zapytania foo [] = 1 & foo [] = 2 jest poprawnie analizowany jako {"foo" => ["1", "2"]}, ale build_query zamienia to na "foo = 1 & foo = 2", które po przeanalizowaniu ponownie daje {"foo" => "2"}.
Raels
45

Aby uzyskać czyste rozwiązanie Ruby, połącz URI.parsez CGI.parse(można tego użyć nawet jeśli Rails / Rack itp. Nie są wymagane):

CGI.parse(URI.parse(url).query) 
# =>  {"name1" => ["value1"], "name2" => ["value1", "value2", ...] }
alup
źródło
33

Istnieje więcej niż jeden sposób rozwiązania problemu. Inni pokazali ci kilka sztuczek. Znam inną sztuczkę. Oto moja próba: -

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

Przeczytaj dokumentację dotyczącą metody ::decode_www_form.

Arup Rakshit
źródło
13

Sprawdź adresowalny klejnot - popularny zamiennik modułu URI Ruby, który ułatwia analizowanie zapytań:

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

(Najwyraźniej obsługuje również kodowanie / dekodowanie parametrów, w przeciwieństwie do URI)

Yarin
źródło
-3

W swoim kontrolerze powinieneś mieć dostęp do słownika (hash) o nazwie params. Tak więc, jeśli wiesz, jakie są nazwy każdego parametru zapytania, po prostu zrób to, params[:param1]aby uzyskać do niego dostęp ... Jeśli nie wiesz, jakie są nazwy parametrów, możesz przeszukać słownik i uzyskać klucze.

Kilka prostych przykładów tutaj .

kafuchau
źródło
OK, wiedziałem, że działa dobrze w kontrolerze z żądanym adresem URL, ale jak to zrobić w przypadku innych dowolnych adresów URL?
Flackou