开发者

Redefining String's gsub

I am new to ruby and I just come across my first tricky problem. I am trying to redefine some methods of String in order to attach some functionality around them. The problematic method appears to be gsub. (EDIT) Let me paste my main.rb that showcases this error.

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

This is my starting point and I expect this to work just as the original String does. Unfotunately, with this redefinition in place, some existing code breaks.

As you can see in this script, I try to load Sinatra and serve a page. When I do this and request the index, the web server fails with the following output in the console.

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

The first exception (httpresponse.rb:172) is on the line

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

and the second error is caused by the result of (accesslog.rb:50)

format_string.gsub(/\%(?:\{(.*?)\})?开发者_Python百科>?([a-zA-Z%])/)

From the above, it appers that I am using Ruby 1.9.1 (even though ruby -v gives me 1.9.2p0). I'm on Ubuntu 10.04. It is true that there may be something wrong in my configuration of Ruby, installing it in Ubuntu was a bit messy.

So, to sum up, why does my redefinition of gsub behave differenlty than the original gsub?


MRI Ruby's internal C code implementation of gsub does some magic to set up $&, $1, and so on in the calling method. When you redefine gsub, they end up getting set in your redefinition, rather than the caller of your redefinition.

I don't know a way around this in MRI. In Rubinius, enough of the internals are implemented in Ruby and made accessible to user-level code that it is possible. This is something Yehuda Katz touches on in this post.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜