วิธีแยกพารามิเตอร์ URL จาก URL ด้วย Ruby หรือ Rails


137

ฉันมีบาง 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'}

คุณมีคำแนะนำไหม


1
Hash[*string.split('&').collect{|i|i.split('=')}.flatten] สิ่งนี้จะใช้ได้เช่นกัน แต่อาจเป็นตัวเลือกที่แย่ที่สุดสำหรับกรณีนี้ แต่ถึงอย่างนั้นคุณก็อาจพบว่าตัวอย่างนี้น่าสนใจ (โพสต์เป็นความคิดเห็นเนื่องจากฉันไม่ได้พิจารณาคำตอบนี้ :-))
Vojto

คำตอบ:


162

ฉันคิดว่าคุณต้องการเปลี่ยนสตริง URL ที่กำหนดให้เป็นแฮช?

คุณสามารถลอง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"]}

1
ตกลงนั่นคือสิ่งที่ฉันพลาด! มันสมบูรณ์แบบเมื่อใช้กับ URI.parse: CGI.parse (URI.parse (" example.com/ ... ) คืนค่าแฮชที่ต้องการขอบคุณสำหรับความช่วยเหลือของคุณ
Flackou

91
เพื่อความชัดเจน @Flackou ต้องการสิ่งนี้: CGI.parse(URI.parse(url).query)
glenn jackman

ฉันยังไม่ได้ทดสอบสิ่งนี้ แต่คีย์แรกที่แสดงรายการซึ่งมี URL เต็มดูเหมือนว่าผิดจริงๆ
เลวี

2
จริงๆแล้วฉันต้องใช้สิ่งนี้: CGI::parse(URI::parse(url).query)
portforwardpodcast

151

ฉันพบว่าตัวเองต้องการสิ่งเดียวกันสำหรับโครงการล่าสุด การสร้างโซลูชันของลีวายส์นี่เป็นวิธีที่สะอาดและเร็วกว่า:

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

น้ำหนักเบากว่าการล้อเลียนคำขอ Rack
Gareth

2
หาดี หากคุณมีพารามิเตอร์แบบง่าย (ไม่ซ้อนกัน) และมีความอ่อนไหวด้านประสิทธิภาพ Rack :: Utils.parse_query อาจเป็นที่สนใจ รหัสมีมูลค่าการอ่าน: github.com/rack/rack/blob/master/lib/rack/utils.rb
Levi

ขอบคุณก็มีประโยชน์มาก :)
บลูสมิ ธ

นี้ทำงานได้ดี param1=value1&param1=value2แต่ไม่ได้ทำงานให้กับช่องทำเครื่องหมายที่มีชื่อเดียวกัน: ค่าที่สองสำคัญกว่าค่าแรก
B เซเว่น

สำหรับทุกคนที่กำลังมองหาสิ่งที่ตรงกันข้ามมันRack::Utils.build_nested_query(params)(หรือRack::Utils.build_query(params)ถ้าแยกกับRack::Utils.parse_query)
zelanix

99

เพิ่งปรับปรุงด้วยคำตอบ Levi ด้านบน -

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

สำหรับสตริงเช่น URL ด้านบนมันจะกลับมา

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

7
คำตอบที่ดี ง่ายประมวลผล 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

45

สำหรับโซลูชัน Ruby ล้วนๆรวมURI.parseกับCGI.parse(สามารถใช้ได้แม้ว่าไม่จำเป็นต้องใช้ Rails / Rack ฯลฯ ):

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

33

มีมากกว่าหนึ่งวิธีในการแก้ปัญหาของคุณ คนอื่นแสดงให้คุณเห็นถึงเทคนิคบางอย่าง ฉันรู้เคล็ดลับอื่น นี่คือความพยายามของฉัน: -

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

อ่าน docomentation ::decode_www_formวิธีการ


13

ตรวจสอบแอดเดรสอัญมณี - ทดแทนที่นิยมสำหรับโมดูล URI ทับทิมที่ทำให้แบบสอบถามแยกง่าย:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.