Bagaimana cara mengekstrak parameter URL dari URL dengan Ruby atau Rails?

139

Saya memiliki beberapa URL, seperti

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

dan saya ingin mengekstrak parameter dari URL ini dan memasukkannya ke dalam Hash. Jelas, saya bisa menggunakan ekspresi reguler, tetapi saya hanya ingin tahu apakah ada cara yang lebih mudah untuk melakukannya dengan Ruby atau Rails. Saya belum menemukan apa pun di modul Ruby URItetapi mungkin saya melewatkan sesuatu.

Sebenarnya, saya membutuhkan metode yang akan melakukannya:

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

Apakah Anda punya nasihat?

Flackou
sumber
1
Hash[*string.split('&').collect{|i|i.split('=')}.flatten] Ini akan berhasil juga, tapi mungkin itu pilihan terburuk untuk kasus ini. Tapi tetap saja Anda mungkin menganggap cuplikan ini menarik. (Posting sebagai komentar karena saya tidak menganggap ini sebagai jawaban :-))
Vojto

Jawaban:

163

Saya pikir Anda ingin mengubah string URL apa pun menjadi HASH?

Anda dapat mencoba http://www.ruby-doc.org/stdlib/libdoc/cgi/rdoc/classes/CGI.html#M000075

require 'cgi'

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

kembali

{"param1"=>["value1"], "param2"=>["value2"], "param3"=>["value3"]}
Luqman
sumber
2
Oke, itu yang saya lewatkan! Sempurna jika digunakan dengan URI.parse: CGI.parse (URI.parse (" example.com/… ) mengembalikan Hash yang diinginkan. Terima kasih atas bantuan Anda.
Flackou
92
Untuk kejelasan, @Flackou menginginkan ini: CGI.parse(URI.parse(url).query)
glenn jackman
Saya belum menguji ini, tetapi kunci pertama yang terdaftar, yang berisi url lengkap, tampaknya sangat salah.
Levi
2
Saya sebenarnya harus menggunakan ini: CGI::parse(URI::parse(url).query)
portforwardpodcast
152

Saya menemukan diri saya membutuhkan hal yang sama untuk proyek baru-baru ini. Berdasarkan solusi Levi's, inilah metode yang lebih bersih dan lebih cepat:

Rack::Utils.parse_nested_query 'param1=value1&param2=value2&param3=value3'
# => {"param1"=>"value1", "param2"=>"value2", "param3"=>"value3"}
Arthur Gunn
sumber
Jauh lebih ringan daripada mengejek permintaan Rack
Gareth
2
Temuan bagus. Jika Anda memiliki parameter sederhana (tidak bersarang) dan peka terhadap kinerja, Rack :: Utils.parse_query mungkin menarik. Kode ini layak dibaca: github.com/rack/rack/blob/master/lib/rack/utils.rb
Levi
Terima kasih, ini sangat berguna :)
Blue Smith
Ini bekerja dengan baik tetapi tidak bekerja untuk kotak centang dengan nama yang sama: param1=value1&param1=value2. Nilai kedua mengalahkan nilai pertama.
B Tujuh
Bagi siapa saja yang mencari kebalikannya, itu Rack::Utils.build_nested_query(params) (atau Rack::Utils.build_query(params)jika diurai dengan Rack::Utils.parse_query).
zelanix
101

Baru saja ditingkatkan dengan jawaban Levi di atas -

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

Untuk string seperti url di atas, itu akan kembali

{ "par" => "hello", "par2" => "bye" } 
rtdp
sumber
7
jawaban yang bagus. sederhana, memproses URL lengkap seperti yang diminta op, dan nilai hasilnya adalah string, bukan array, seperti di jawaban lain. Terima kasih.
jackocnr
3
Seperti yang saya komentari di atas, bagi siapa pun yang mencari kebalikannya, itu Rack::Utils.build_query(params).
zelanix
1
Hati-hati - tidak sebaliknya, setidaknya di Ruby 1.8.7 / Rails 2.3. String kueri foo [] = 1 & foo [] = 2 diurai dengan benar sebagai {"foo" => ["1", "2"]}, tetapi build_query mengubahnya menjadi "foo = 1 & foo = 2", yang ketika diurai sekali lagi menghasilkan {"foo" => "2"}.
Raels
48

Untuk solusi Ruby murni menggabungkan URI.parsedengan CGI.parse(ini dapat digunakan bahkan jika Rails / Rack dll tidak diperlukan):

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

Ada lebih dari satu cara, untuk menyelesaikan masalah Anda. Orang lain telah menunjukkan beberapa trik. Saya tahu trik lain. Inilah percobaan saya: -

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

Bacalah dokumentasi metode ::decode_www_form.

Arup Rakshit
sumber
13

Lihat permata yang dapat dialamatkan - pengganti populer untuk modul URI Ruby yang membuat penguraian kueri menjadi mudah:

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

(Ini juga tampaknya menangani encoding / decoding param, tidak seperti URI)

Yarin
sumber
-3

Di Controller Anda, Anda seharusnya bisa mengakses kamus (hash) yang dipanggil params. Jadi, jika Anda tahu nama setiap parameter kueri, lakukan sajaparams[:param1] untuk mengaksesnya ... Jika Anda tidak tahu apa nama parameternya, Anda dapat menelusuri kamus dan mendapatkan kuncinya.

Beberapa contoh sederhana di sini .

kafuchau
sumber
Oke, saya tahu itu, ini berfungsi dengan baik di pengontrol dengan URL yang diminta, tetapi bagaimana melakukannya untuk URL sembarang orang lain?
Flackou