2011-02-25 30 views
4

我是新來的紅寶石,我剛剛遇到我的第一個棘手的問題。我試圖重新定義String的一些方法,以便在它們周圍附加一些功能。有問題的方法似乎是gsub。 (編輯)讓我粘貼我的main.rb展示這個錯誤。重新定義字符串的gsub

require 'rubygems' if RUBY_VERSION < "1.9" 
require 'sinatra' 

class String 
    alias_method :old_gsub, :gsub 
    def gsub (*params, &block) 
     old_gsub *params, &block 
    end 
end 

get '/' do 
    s="Hello world! " 
end 

這是我的出發點,我期望它能像原始String一樣工作。不幸的是,隨着這種重新定義,一些現有的代碼被打破。

正如您在此腳本中看到的,我嘗試加載Sinatra並提供頁面。當我這樣做並請求索引時,Web服務器將失敗,並在控制檯中顯示以下輸出。

127.0.0.1 - - [25/Feb/2011 17:56:26] "GET/HTTP/1.1" 200 13 0.0012 [2011-02-25 17:56:26] ERROR NoMethodError: undefined method `upcase' for nil:NilClass /usr/local/ruby/lib/ruby/1.9.1/webrick/httpresponse.rb:172:in `block (2 levels) in send_header' /data/Dropbox/Ruby/RubyTrack/lib/main.rb:227:in `gsub' /data/Dropbox/Ruby/RubyTrack/lib/main.rb:227:in `gsub' /usr/local/ruby/lib/ruby/1.9.1/webrick/httpresponse.rb:172:in `block in send_header' +plus more stuff in the trace
[2011-02-25 17:56:26] ERROR NoMethodError: undefined method `[]' for nil:NilClass /usr/local/ruby/lib/ruby/1.9.1/webrick/accesslog.rb:52:in `block in format' /data/Dropbox/Ruby/RubyTrack/lib/main.rb:227:in `gsub' /data/Dropbox/Ruby/RubyTrack/lib/main.rb:227:in `gsub' /usr/local/ruby/lib/ruby/1.9.1/webrick/accesslog.rb:50:in `format' +more stuff in the trace

第一個例外(httpresponse.rb:172)是上線

tmp = key.gsub(/\bwww|^te$|\b\w/){ $&.upcase } 

和第二誤差由(accesslog.rb:50)的結果所造成

format_string.gsub(/\%(?:\{(.*?)\})?>?([a-zA-Z%])/) 

從上面可以看出,我使用的是Ruby 1.9.1(即使ruby -v給我1.9.2p0)。我在Ubuntu 10.04上。確實,在我的Ruby配置中可能有問題,在Ubuntu中安裝它有點麻煩。

因此,總而言之,爲什麼我對gsub的重新定義表現出與原始gsub不同?

+1

爲什麼不直接向String中添加新的方法?只需將您的gsub重新定義爲不同的名稱即可。 – david4dev 2011-02-25 15:46:19

+0

Ruby的這個特性是我嘗試這種語言的原因。我是一個謙虛的博士做一些研究,透明地編輯程序的行爲來執行某些安全屬性。因此,我需要爲現有功能提供不同的定義。 – Yiannis 2011-02-25 15:54:18

+1

你可以發佈一些錯誤代碼嗎? – DanSingerman 2011-02-25 16:43:54

回答

2

MRI Ruby的內部C代碼實現gsub在調用方法中設置了$&,$1等等。當您重新定義gsub時,它們最終會在重新定義中設置,而不是重新定義的調用者。

我不知道在MRI中解決這個問題。在Rubinius中,足夠的內部是在Ruby中實現的,並且可以通過用戶級代碼訪問它,因爲它可能是。這是耶胡達卡茨在this post接觸到的東西。