覆盖Ruby类方法;无法解析名称空间

时间:2015-05-12 19:32:38

标签: ruby-on-rails ruby

我想覆盖this method,在此缩写。

class Redis
  module Connection
    class Ruby
      include Redis::Connection::CommandHelper

      def self.connect(config)
        if config[:scheme] == "unix"
          sock = UNIXSocket.connect(config[:path], config[:timeout])
        else
          sock = TCPSocket.connect(config[:host], config[:port], config[:timeout])
          if config[:scheme] == "rediss" or config[:use_ssl]
            ssl_context = OpenSSL::SSL::SSLContext.new
            ssl_context.ca_file = config[:ssl_ca_file]
            ssl_context.key = config[:ssl_key]
            ssl_context.cert = config[:ssl_cert]
            ssl_context.verify_mode = config[:ssl_verify_mode]
            ssl_client = OpenSSL::SSL::SSLSocket.new sock, ssl_context
            ssl_client.connect
            sock = ssl_client
          end
        end

        instance = new(sock)
        instance.timeout = config[:timeout]
        instance.set_tcp_keepalive config[:tcp_keepalive]
        instance
      end
    end
  end
end

所以我创建了一个RubyGem,它对'redis'有一个运行时依赖。在gem的lib文件夹中,我有一个带

的文件
begin
  require "openssl"
rescue LoadError
  #ignore the error, ssl support will not work
end

Redis::Connection::Ruby.class_eval do
  def self.connect(config)
    if config[:scheme] == "unix"
      sock = UNIXSocket.connect(config[:path], config[:timeout])
    else
      sock = TCPSocket.connect(config[:host], config[:port], config[:timeout])
      if config[:scheme] == "rediss" or config[:use_ssl]
        ssl_context = OpenSSL::SSL::SSLContext.new
        ssl_context.ca_file = config[:ssl_ca_file]
        ssl_context.key = config[:ssl_key]
        ssl_context.cert = config[:ssl_cert]
        ssl_context.verify_mode = config[:ssl_verify_mode]
        ssl_client = OpenSSL::SSL::SSLSocket.new sock, ssl_context
        ssl_client.connect
        sock = ssl_client
      end
    end

    instance = new(sock)
    instance.timeout = config[:timeout]
    instance.set_tcp_keepalive config[:tcp_keepalive]
    instance
  end
end

这是我得到的错误:

/vagrant/misinformed/redis-rb-ssl/lib/redis/connection/ruby.rb:7:in `<top (required)>': uninitialized constant Redis::Connection::Ruby (NameError)
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/redis-3.2.1/lib/redis/connection.rb:9:in `require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/redis-3.2.1/lib/redis/connection.rb:9:in `<top (required)>'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/redis-3.2.1/lib/redis.rb:2631:in `require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/redis-3.2.1/lib/redis.rb:2631:in `<top (required)>'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler/runtime.rb:76:in `require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler/runtime.rb:76:in `block (2 levels) in require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler/runtime.rb:72:in `each'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler/runtime.rb:72:in `block in require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler/runtime.rb:61:in `each'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler/runtime.rb:61:in `require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler.rb:134:in `require'
    from /vagrant/dragondoor/config/application.rb:7:in `<top (required)>'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.1.9/lib/rails/commands/commands_tasks.rb:146:in `require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.1.9/lib/rails/commands/commands_tasks.rb:146:in `require_application_and_environment!'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.1.9/lib/rails/commands/commands_tasks.rb:68:in `console'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.1.9/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.1.9/lib/rails/commands.rb:17:in `<top (required)>'
    from bin/rails:8:in `require'
    from bin/rails:8:in `<main>'

如何覆盖该方法?我的猜测是我要么命名空间错误,要么我需要require一些东西,但我无法得到任何工作。

更新:

根据删除的评论,我也尝试了

begin
  require "openssl"
rescue LoadError
  #ignore the error, ssl support will not work
end

class Redis
  module Connection
    Ruby.class_evel do
      def self.connect(config)
        if config[:scheme] == "unix"
          sock = UNIXSocket.connect(config[:path], config[:timeout])
        else
          sock = TCPSocket.connect(config[:host], config[:port], config[:timeout])
          if config[:scheme] == "rediss" or config[:use_ssl]
            ssl_context = OpenSSL::SSL::SSLContext.new
            ssl_context.ca_file = config[:ssl_ca_file]
            ssl_context.key = config[:ssl_key]
            ssl_context.cert = config[:ssl_cert]
            ssl_context.verify_mode = config[:ssl_verify_mode]
            ssl_client = OpenSSL::SSL::SSLSocket.new sock, ssl_context
            ssl_client.connect
            sock = ssl_client
          end
        end

        instance = new(sock)
        instance.timeout = config[:timeout]
        instance.set_tcp_keepalive config[:tcp_keepalive]
        instance
      end
    end
  end
end

这似乎让我走得更远,但仍然收到错误信息

/home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.2.0/lib/rails/app_rails_loader.rb:39: warning: Insecure world writable dir /vagrant/dragondoor in PATH, mode 040777
/home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler.rb:302: warning: Insecure world writable dir /vagrant/dragondoor in PATH, mode 040777
/vagrant/misinformed/redis-rb-ssl/lib/redis/connection/ruby.rb:9:in `<module:Connection>': uninitialized constant Redis::Connection::Ruby (NameError)
    from /vagrant/misinformed/redis-rb-ssl/lib/redis/connection/ruby.rb:8:in `<class:Redis>'
    from /vagrant/misinformed/redis-rb-ssl/lib/redis/connection/ruby.rb:7:in `<top (required)>'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/redis-3.2.1/lib/redis/connection.rb:9:in `require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/redis-3.2.1/lib/redis/connection.rb:9:in `<top (required)>'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/redis-3.2.1/lib/redis.rb:2631:in `require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/redis-3.2.1/lib/redis.rb:2631:in `<top (required)>'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler/runtime.rb:76:in `require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler/runtime.rb:76:in `block (2 levels) in require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler/runtime.rb:72:in `each'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler/runtime.rb:72:in `block in require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler/runtime.rb:61:in `each'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler/runtime.rb:61:in `require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/bundler-1.7.12/lib/bundler.rb:134:in `require'
    from /vagrant/dragondoor/config/application.rb:7:in `<top (required)>'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.1.9/lib/rails/commands/commands_tasks.rb:146:in `require'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.1.9/lib/rails/commands/commands_tasks.rb:146:in `require_application_and_environment!'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.1.9/lib/rails/commands/commands_tasks.rb:68:in `console'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.1.9/lib/rails/commands/commands_tasks.rb:40:in `run_command!'
    from /home/vagrant/.rbenv/versions/2.1.5/lib/ruby/gems/2.1.0/gems/railties-4.1.9/lib/rails/commands.rb:17:in `<top (required)>'
    from bin/rails:8:in `require'
    from bin/rails:8:in `<main>'

1 个答案:

答案 0 :(得分:0)

尝试将require 'redis'添加到您修补方法的文件中:

require 'redis'

class Redis
  module Connection
    class Ruby
      def self.connect(config)
        puts 'the method is overriden'
      end
    end
  end
end