Как извлечь параметры URL из URL с помощью Ruby или Rails?

139

У меня есть несколько URL-адресов, например

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

и я хотел бы извлечь параметры из этих URL-адресов и получить их в виде хэша. Очевидно, я мог бы использовать регулярные выражения, но мне просто было интересно, есть ли более простые способы сделать это с помощью Ruby или Rails. Я ничего не нашел в модуле Ruby, URIно, возможно, я что-то упустил.

На самом деле мне нужен метод, который бы это делал:

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

Не могли бы вы дать совет?

Flackou
источник
1
Hash[*string.split('&').collect{|i|i.split('=')}.flatten] Это тоже сработает, но, вероятно, это худший вариант в данном случае. Но все же этот фрагмент может показаться вам интересным. (Публикуется как комментарий, поскольку я не считаю это ответом :-))
Войто

Ответы:

163

Я думаю, вы хотите превратить любую заданную строку URL в HASH?

Вы можете попробовать http://www.ruby-doc.org/stdlib/libdoc/cgi/rdoc/classes/CGI.html#M000075

require 'cgi'

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

возвращается

{"param1"=>["value1"], "param2"=>["value2"], "param3"=>["value3"]}
Лукман
источник
2
Хорошо, это был тот, который я пропустил! Он идеален при использовании с URI.parse: CGI.parse (URI.parse (" example.com/… ) возвращает желаемый хэш. Спасибо за вашу помощь.
Flackou
92
Для ясности, @Flackou хочет это: CGI.parse(URI.parse(url).query)
glenn jackman
Я не тестировал это, но первый указанный ключ, содержащий полный URL-адрес, кажется действительно неправильным.
Леви,
2
Мне действительно пришлось использовать это: CGI::parse(URI::parse(url).query)
portforwardpodcast
153

Я обнаружил, что мне нужно то же самое для недавнего проекта. Основываясь на решении Леви, вот более чистый и быстрый метод:

Rack::Utils.parse_nested_query 'param1=value1&param2=value2&param3=value3'
# => {"param1"=>"value1", "param2"=>"value2", "param3"=>"value3"}
Артур Ганн
источник
Гораздо легче, чем издеваться над запросом на стойку
Гарет
2
Хорошая находка. Если у вас есть простые параметры (не вложенные) и они чувствительны к производительности, может быть интересен Rack :: Utils.parse_query. Код стоит прочитать: github.com/rack/rack/blob/master/lib/rack/utils.rb
Леви
Спасибо, очень полезно :)
Blue Smith
Это хорошо работает , но не работает для флажков с тем же именем param1=value1&param1=value2. Второе значение превосходит первое.
B Seven
Для тех, кто ищет обратное, это Rack::Utils.build_nested_query(params)(или Rack::Utils.build_query(params)если его проанализировать Rack::Utils.parse_query).
zelanix
101

Просто улучшено с ответом Леви выше -

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

Для строки, подобной URL-адресу выше, он вернет

{ "par" => "hello", "par2" => "bye" } 
rtdp
источник
7
отличный ответ. simple, обрабатывает полный URL-адрес, как запрашивает op, а значения результатов представляют собой строки, а не массивы, как в других ответах. Спасибо.
jackocnr
3
Как я уже говорил выше, для тех, кто ищет обратное, это Rack::Utils.build_query(params).
zelanix
1
Остерегайтесь - не совсем наоборот, по крайней мере, не в Ruby 1.8.7 / Rails 2.3. Строка запроса foo [] = 1 & foo [] = 2 правильно анализируется как {"foo" => ["1", "2"]}, но build_query превращает это в "foo = 1 & foo = 2", которое при синтаксическом анализе снова дает {"foo" => "2"}.
Raels
48

Для чистого решения Ruby объедините URI.parseс CGI.parse(это можно использовать, даже если Rails / Rack и т. Д. Не требуются):

CGI.parse(URI.parse(url).query) 
# =>  {"name1" => ["value1"], "name2" => ["value1", "value2", ...] }
Алуп
источник
36

Есть несколько способов решить вашу проблему. Другие показали вам некоторые уловки. Я знаю еще одну уловку. Вот моя попытка: -

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

Прочтите документацию по методу ::decode_www_form.

Аруп Ракшит
источник
13

Обратите внимание на адресуемую жемчужину - популярную замену модуля URI Ruby, которая упрощает синтаксический анализ запросов:

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

(Он также, по-видимому, обрабатывает кодирование / декодирование параметров, в отличие от URI)

Ярин
источник
-3

В вашем контроллере вы должны иметь доступ к словарю (хешу) с именем params. Итак, если вы знаете, как называются имена каждого параметра запроса, просто сделайте, params[:param1]чтобы получить к нему доступ ... Если вы не знаете, каковы имена параметров, вы можете пройти по словарю и получить ключи.

Некоторые простые примеры здесь .

кафучау
источник
Хорошо, я знал, что он хорошо работает в контроллере с запрошенным URL-адресом, но как это сделать для других произвольных URL-адресов?
Flackou