代码来自redis-namespace-1.5.3/lib/redis/namespace.rb

它主要是通过method_missing来代理操作实际的redis client

def method_missing(command, *args, &block)
  normalized_command = command.to_s.downcase

  if ADMINISTRATIVE_COMMANDS.include?(normalized_command)
    return super if deprecations?
    call_with_namespace(command, *args, &block)
  elsif COMMANDS.include?(normalized_command)
    call_with_namespace(command, *args, &block)
  elsif @redis.respond_to?(normalized_command) && !deprecations?
    @redis.send(command, *args, &block)
  else
    super
  end
end

def call_with_namespace(command, *args, &block)
  handling = COMMANDS[command.to_s.downcase]

  if handling.nil?
    fail("Redis::Namespace does not know how to handle '#{command}'.")
  end

  (before, after) = handling

  # Modify the local *args array in-place, no need to copy it.
  args.map! {|arg| clone_args(arg)}

  # Add the namespace to any parameters that are keys.
  case before
  when :first
    args[0] = add_namespace(args[0]) if args[0]
  when :all
    args = add_namespace(args)
  when :exclude_first
    first = args.shift
    args = add_namespace(args)
    args.unshift(first) if first
  when :exclude_last
    last = args.pop unless args.length == 1
    args = add_namespace(args)
    args.push(last) if last
  when :exclude_options

  # ...

  result = @redis.send(command, *args, &block)

  # Don't try to remove namespace from a Redis::Future, you can't.
  return result if result.is_a?(Redis::Future)

  # Remove the namespace from results that are keys.
  case after
  when :all
    result = rem_namespace(result)
  when :first
    result[0] = rem_namespace(result[0]) if result
  when :second
    result[1] = rem_namespace(result[1]) if result
  end

  result
end


而给“参数中的键”、“返回值中的键”添加namespace的规则如下

NAMESPACED_COMMANDS = {
  "append"           => [ :first ],
  "bitcount"         => [ :first ],
  "bitop"            => [ :exclude_first ],
  "blpop"            => [ :exclude_last, :first ],
  "brpop"            => [ :exclude_last, :first ],
  "brpoplpush"       => [ :exclude_last ],
  "debug"            => [ :exclude_first ],
  "decr"             => [ :first ],
  # ...