Como extrair parâmetros de URL de um URL com Ruby ou Rails?


137

Eu tenho alguns URLs, como

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

e gostaria de extrair os parâmetros desses URLs e obtê-los em um Hash. Obviamente, eu poderia usar expressões regulares, mas estava me perguntando se havia maneiras mais fáceis de fazer isso com Ruby ou Rails. Não encontrei nada no módulo Ruby, URImas talvez tenha perdido alguma coisa.

Na verdade, preciso de um método que faça isso:

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

Você gostaria de receber alguns conselhos?


1
Hash[*string.split('&').collect{|i|i.split('=')}.flatten] Isso também funcionaria, mas é provavelmente a pior opção para este caso. Mas você ainda pode achar interessante esse trecho. (Publicando como comentário, já que eu não considero isso uma resposta :-))
Vojto

Respostas:


162

Eu acho que você deseja transformar qualquer string de URL em HASH?

Você pode tentar http://www.ruby-doc.org/stdlib/libdoc/cgi/rdoc/classes/CGI.html#M000075

require 'cgi'

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

retorna

{"param1"=>["value1"], "param2"=>["value2"], "param3"=>["value3"]}

1
OK, foi esse que eu perdi! É perfeito quando usado com URI.parse: CGI.parse (URI.parse (" example.com/... ) retorna o Hash desejado Obrigado por sua ajuda..
Flackou

91
Para maior clareza, @Flackou quer isto: CGI.parse(URI.parse(url).query)
Glenn Jackman

Não testei isso, mas a primeira chave listada, contendo o URL completo, parece realmente errada.
Levi

2
Eu realmente tive que usar isto: CGI::parse(URI::parse(url).query)
portforwardpodcast

151

Eu me vi precisando da mesma coisa para um projeto recente. Com base na solução da Levi, aqui está um método mais limpo e rápido:

Rack::Utils.parse_nested_query 'param1=value1&param2=value2&param3=value3'
# => {"param1"=>"value1", "param2"=>"value2", "param3"=>"value3"}

Muito mais leve do que zombando de um pedido cremalheira
Gareth

2
Boa descoberta. Se você possui parâmetros simples (não aninhados) e é sensível ao desempenho, o Rack :: Utils.parse_query pode ser interessante. Vale a pena ler o código: github.com/rack/rack/blob/master/lib/rack/utils.rb
Levi

Obrigado, é muito útil :)
Blue Smith

Isso funciona bem, mas não funciona para caixas com o mesmo nome: param1=value1&param1=value2. O segundo valor supera o primeiro.
B Seven

Para quem procura o inverso, é Rack::Utils.build_nested_query(params)(ou Rack::Utils.build_query(params)se analisado Rack::Utils.parse_query).
Zelanix

99

Apenas melhorado com a resposta Levi acima -

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

Para uma string como a URL acima, ela retornará

{ "par" => "hello", "par2" => "bye" } 

7
Ótima resposta. simple, processa a URL completa como o op pede, e os valores do resultado são strings em vez de matrizes, como nas outras respostas. obrigado.
jackocnr

3
Como comentei acima, para quem procura o inverso, é Rack::Utils.build_query(params).
Zelanix

1
Cuidado - não exatamente o inverso, pelo menos não no Ruby 1.8.7 / Rails 2.3. Uma string de consulta foo [] = 1 & foo [] = 2 é analisada corretamente como {"foo" => ["1", "2"]}, mas o build_query transforma isso em "foo = 1 & foo = 2", que quando analisado novamente produz {"foo" => "2"}.
Raels 20/07/16

44

Para uma solução Ruby pura, combine URI.parsecom CGI.parse(isso pode ser usado mesmo que Rails / Rack etc. não sejam necessários):

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

33

Existem mais de uma maneira de resolver seu problema. Outros mostrou alguns truques. Eu conheço outro truque. Aqui está a minha tentativa: -

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

Leia a documentação do método ::decode_www_form.


13

Confira a gema endereçável - um substituto popular para o módulo URI do Ruby que facilita a análise de consultas:

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

(Ele também aparentemente lida com param codificação / decodificação, ao contrário do URI)


-3

No seu Controller, você poderá acessar um dicionário (hash) chamado params. Então, se você sabe quais são os nomes de cada parâmetro de consulta, basta fazerparams[:param1] acessá-lo ... Se você não souber quais são os nomes dos parâmetros, poderá percorrer o dicionário e obter as chaves.

Alguns exemplos simples aqui .


OK, eu sabia disso, funciona bem no controlador com a URL solicitada, mas como fazer isso para outras URLs arbitrárias?
Flackou 23/03/10
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.