2010-01-27 83 views
13

我想從URL中取出一個參數,但不知道它是哪個參數,然後重新組裝URL。Ruby中從URL中刪除參數的最優雅方式是什麼?

我想這並不難,我自己寫一些使用CGI或URI的東西,但我想這種功能已經存在了。有什麼建議麼?

在:

http://example.com/path?param1=one&param2=2&param3=something3 

日期:

http://example.com/path?param2=2&param3=something3 

回答

7

尋址創業板將很好地做到這一點;請看優秀回答者:田文。但是如果你想推出自己的產品,那麼這就是如何。這段代碼有高雅的唯一要求是,它隱藏醜陋的方法:

#!/usr/bin/ruby1.8 

def reject_param(url, param_to_reject) 
    # Regex from RFC3986 
    url_regex = %r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$" 
    raise "Not a url: #{url}" unless url =~ url_regex 
    scheme_plus_punctuation = $1 
    authority_with_punctuation = $3 
    path = $5 
    query = $7 
    fragment = $9 
    query = query.split('&').reject do |param| 
    param_name = param.split(/[=;]/).first 
    param_name == param_to_reject 
    end.join('&') 
    [scheme_plus_punctuation, authority_with_punctuation, path, '?', query, fragment].join 
end 

url = "http://example.com/path?param1=one&param2=2&param3=something3" 
p url 
p reject_param(url, 'param2') 

# => "http://example.com/path?param1=one&param2=2&param3=something3" 
# => "http://example.com/path?param1=one&param3=something3" 
+2

Upvote使用RFC中的實際正則表達式。很好的參考。 – btelles 2010-01-27 23:50:11

+2

分號也可以用來分隔查詢參數,您的'reject_param'不適用於這個有效的URL'http://example.com/path?param1 = one; param2 = 2; param3 = something3'。 – 2010-11-24 20:09:25

+0

@mu太短,謝謝。我修改了(但未經測試)代碼以允許';'以及'='。 – 2010-11-24 21:30:52

5

我想出了這樣的事情

def uri_remove_param(uri, params = nil) 
    return uri unless params 
    params = Array(params) 
    uri_parsed = URI.parse(uri) 
    return uri unless uri_parsed.query 
    escaped = uri_parsed.query.grep(/&/).size > 0 
    new_params = uri_parsed.query.gsub(/&/, '&').split('&').reject { |q| params.include?(q.split('=').first) } 
    uri = uri.split('?').first 
    amp = escaped ? '&' : '&' 
    "#{uri}?#{new_params.join(amp)}" 
end 
+0

給自己勾上勾號;我更喜歡你的答案。 URI.parse?另一個方便的圖書館我一無所知。哦,你的參數= [參數]如果......線?你可以用params = Array(params)替換它。當然,我在SO上學到了這個技巧。 – 2010-01-27 21:43:55

+0

params = Array(params)很酷! – dimus 2010-05-10 19:51:03

+1

實際上在玩Array(params)一段時間之後...... Array({})應謹慎使用,因爲它也會將散列轉換爲數組。 – dimus 2010-06-07 18:48:44

26

也許題外話,但任何人誰是一個小試圖在rails應用程序的上下文中執行此操作,您只需執行以下操作:

url_for(params.except(:name_of_param_to_delete)) 

NB在rails v2.3.9中測試。

+0

和'except'的對面是'slice' – lulalala 2013-05-14 10:17:48

+0

非常聰明的解決方案! – Gunchars 2013-05-29 09:25:32

+0

非常好,謝謝! – Agustin 2014-09-18 23:23:37

31

我更喜歡使用:

require 'addressable/uri' 

uri = Addressable::URI.parse('http://example.com/path?param1=one&param2=2&param3=something3') 

params = uri.query_values #=> {"param1"=>"one", "param2"=>"2", "param3"=>"something3"} 
params.delete('param1') #=> "one" 
uri.query_values = params #=> {"param2"=>"2", "param3"=>"something3"} 

uri.to_s #=> "http://example.com/path?param2=2&param3=something3" 
+1

工作就像一個魅力! Github尋址地址:https://github.com/sporkmonger/addressable/tree/ – ankimal 2012-10-17 17:30:32

+2

這比我的解決方案好得多。 – 2013-05-26 05:11:45

15

如果你不希望包括一個額外的寶石,如果你不想讓討厭的正則表達式,這裏是我的首選方式:

require 'cgi' 
require 'uri' 

url = "http://example.com/path?param1=one&param2=2&param3=something3" 

uri = URI(url) #=> #<URI::HTTP:0x007fbe25141a78 URL:http://example.com/path?param1=one&param2=2&param3=something3> 
params = CGI.parse(uri.query || "") #=> {"param1"=>["one"], "param2"=>["2"], "param3"=>["something3"]} 
params.delete('param1') #=> ["one"] 
uri.query = URI.encode_www_form(params) #=> "param2=2&param3=something3" 

uri.to_s #=> "http://example.com/path?param2=2&param3=something3" 
+1

+1使用stdlib – Puhlze 2013-05-26 05:43:14

+2

我會修改CGI解析像這樣處理缺少的參數...'CGI.parse(uri.query ||「」)'否則解析引發異常。 – 2016-02-05 20:58:36

3

一行應該是足夠的:

url.sub(/\?param_to_remove=[^&]*/, '?').sub(/\&param_to_remove=[^&]*/, '').sub(/\?$/,'') 
+0

正是我在找的東西!謝謝! – viniciusnz 2014-02-07 13:32:23

+0

在param_to_remove第一次出現的情況下不正確 – 2017-05-03 08:49:11

相關問題