Làm cách nào để trích xuất các tham số URL từ một URL bằng Ruby hoặc Rails?


137

Tôi có một số URL, như

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

và tôi muốn trích xuất các tham số từ các URL này và nhận chúng trong Hash. Rõ ràng, tôi có thể sử dụng các biểu thức thông thường, nhưng tôi chỉ tự hỏi liệu có cách nào dễ dàng hơn để làm điều đó với Ruby hoặc Rails. Tôi chưa tìm thấy gì trong mô-đun Ruby URInhưng có lẽ tôi đã bỏ lỡ điều gì đó.

Trong thực tế, tôi cần một phương pháp sẽ làm điều đó:

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

Bạn sẽ có một số lời khuyên?


1
Hash[*string.split('&').collect{|i|i.split('=')}.flatten] Điều này cũng sẽ làm việc, nhưng nó có thể là lựa chọn tồi tệ nhất cho trường hợp này. Nhưng bạn vẫn có thể thấy đoạn trích này thú vị. (Đăng dưới dạng nhận xét vì tôi không coi đây là câu trả lời :-))
Vojto

Câu trả lời:


162

Tôi nghĩ rằng bạn muốn biến bất kỳ chuỗi URL đã cho nào thành HASH?

Bạn có thể thử http://www.ruby-doc.org/stdlib/libdoc/cgi/rdoc/groupes/CGI.html#M000075

require 'cgi'

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

trả lại

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

1
OK, đó là người tôi đã bỏ lỡ! Thật hoàn hảo khi được sử dụng với URI.parse: CGI.parse (URI.parse (" example.com/iêu ) trả về Hash mong muốn. Cảm ơn sự giúp đỡ của bạn.
Flackou 23/03

91
Để rõ ràng, @Flackou muốn này: CGI.parse(URI.parse(url).query)
glenn jackman

Tôi đã không kiểm tra điều này, nhưng khóa đầu tiên được liệt kê, chứa url đầy đủ, có vẻ thực sự sai.
Levi

2
Tôi thực sự đã phải sử dụng điều này: CGI::parse(URI::parse(url).query)
portforwardpodcast

151

Tôi thấy mình cần điều tương tự cho một dự án gần đây. Dựa trên giải pháp của Levi, đây là một phương pháp nhanh hơn và sạch hơn:

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

Nhẹ hơn nhiều so với chế nhạo một yêu cầu Rack
Gareth

2
Tìm tốt Nếu bạn có các thông số đơn giản (không lồng nhau) và nhạy cảm về hiệu năng, Rack :: Utils.parse_query có thể được quan tâm. Mã này đáng để đọc: github.com/rack/rack/blob/master/lib/rack/utils.rb
Levi

Cảm ơn bạn, nó rất hữu ích :)
Blue Smith

Điều này hoạt động tốt nhưng không hoạt động cho các hộp kiểm có cùng tên : param1=value1&param1=value2. Giá trị thứ hai hơn hẳn giá trị thứ nhất.
B Bảy

Đối với bất cứ ai tìm kiếm nghịch đảo, nó Rack::Utils.build_nested_query(params)(hoặc Rack::Utils.build_query(params)nếu được phân tích cú pháp Rack::Utils.parse_query).
zelanix

99

Chỉ cần cải thiện với câu trả lời của Levi ở trên -

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

Đối với một chuỗi như url trên, nó sẽ trả về

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

7
câu trả lời chính xác. đơn giản, xử lý URL đầy đủ như op hỏi và các giá trị kết quả là các chuỗi thay vì các mảng, như trong các câu trả lời khác. cảm ơn.
jackocnr

3
Như tôi đã nhận xét ở trên, cho bất cứ ai tìm kiếm nghịch đảo, đó là Rack::Utils.build_query(params).
zelanix

1
Cẩn thận - không hoàn toàn ngược lại, ít nhất là không trong Ruby 1.8.7 / Rails 2.3. Một chuỗi truy vấn của foo [] = 1 & foo [] = 2 được phân tích chính xác là {"foo" => ["1", "2"]}, nhưng build_query biến nó thành "foo = 1 & foo = 2", khi được phân tích cú pháp một lần nữa mang lại {"foo" => "2"}.
Raels

44

Đối với giải pháp Ruby thuần túy kết hợp URI.parsevới CGI.parse(điều này có thể được sử dụng ngay cả khi Rails / Rack, v.v. không bắt buộc):

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

33

Có nhiều hơn một cách, để giải quyết vấn đề của bạn. Những người khác đã chỉ cho bạn một số thủ thuật. Tôi biết một mẹo khác. Đây là thử của tôi: -

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

Đọc các tài liệu phương pháp của ::decode_www_form.


13

Kiểm tra đá quý có thể đánh địa chỉ - một thay thế phổ biến cho mô-đun URI của Ruby giúp phân tích cú pháp truy vấn dễ dàng:

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

(Nó cũng rõ ràng xử lý mã hóa / giải mã param, không giống như URI)


-3

Trong Trình điều khiển của bạn, bạn sẽ có thể truy cập từ điển (hàm băm) được gọi params. Vì vậy, nếu bạn biết tên của từng tham số truy vấn là gì, thì hãy làmparams[:param1] để truy cập nó ... Nếu bạn không biết tên của các tham số là gì, bạn có thể duyệt từ điển và lấy khóa.

Một số ví dụ đơn giản ở đây .


OK, tôi biết rằng, nó hoạt động tốt trong bộ điều khiển với URL được yêu cầu, nhưng làm thế nào để làm điều đó cho các URL tùy ý khác?
Flackou
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.