【问题标题】:How to override a lambda variable from a subclass in Ruby?如何覆盖 Ruby 子类中的 lambda 变量?
【发布时间】:2016-12-15 20:54:15
【问题描述】:

我正在使用Redis gem 访问redis,我希望.hgetall 来象征它返回的哈希键。在this thread 中,@pletern 表示猴子修补 gem 的 _hashify 方法的方法。

但是这是不久前的事了,当前的实现使用 lambda 来 Hashify 从 Redis 返回的列表,而不是方法。 See line 2728

我一直在尝试用我自己的实现来“覆盖”这个 lambda,遵循类似的方法:

class MyRedis < Redis

  private

  Hashify =
    lambda { |array|
      hash = Hash.new
      array.each_slice(2) do |field, value|
        hash[field.to_sym] = value
      end
      hash
    }
end

在我的 RedisService 中:

class RedisService
  class << self

    def hgetall(key)
      redis.hgetall("room:"+room_name)
    end

    private

    def redis
      @@redis ||= MyRedis.new
    end

  end
end

我在课堂上玩过,但无法覆盖 gem 中的 Hashify lambda。

【问题讨论】:

  • 您是否尝试过使用链接到的帖子中的给定钩子来实现它? (例如,在您的子类中定义 _hashify 方法?您当前的问题,尝试重新定义 Hashify 常量与您控制实例化的能力有关。例如,如果代码库的任何部分调用 Redis.new 它没有逃出你的子类,会返回Hashify的父类实现@
  • 我只调用过 MyRedis.new,是的,我只是尝试定义 _hashify,但没有成功
  • 你叫什么并不重要。您正在从 Redis 继承所有方法,因此假设您调用 MyRedis::current 这将返回 Redis 实例而不是 MyRedis 实例。

标签: ruby lambda redis symbols monkeypatching


【解决方案1】:

在您的子类中设置您自己的Hashify 并没有帮助,因为Ruby 解释器将使用Redis 中定义的常量,因为调用Hashify.call 的方法也在那里定义。

不过,您可以覆盖 Redis::Hashify。这将导致您的 lambda 用于所有 Redis 连接和warning: already initialized constant Redis::Hashify

require 'redis'

Redis::Hashify = lambda do |array|
  Hash.new.tap do |hash|
    array.each_slice(2) do |field, value|
      hash[field.to_sym] = value
    end
  end
end

请注意,许多开发人员认为编写会产生警告的代码是不好的风格。收到Redis#hgetall的回复后最好修改一下。如果您不介意使用 ActiveSupport,可以使用 Hash#symbolize_keys,例如。

【讨论】:

  • 重复键以使它们成为可以忽略不计的符号是否会导致性能损失,以至于我什至不应该在我的决定中考虑这一点?
  • @AlexTurner 这取决于您期望的响应的大小。重新生成密钥 一项昂贵的操作,但除非您有非常大的响应集,否则它应该足够快。您还可以做的是向 redis.rb 打开一个拉取请求,以便它不使用常量,而是使用类属性。
猜你喜欢
  • 2018-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-03
  • 1970-01-01
  • 2018-07-10
  • 2021-08-24
  • 1970-01-01
相关资源
最近更新 更多