当哈希内容发生变化时,Hook会运行

时间:2017-05-18 08:45:38

标签: ruby hash

当哈希内容发生变化时,我不想做某事。我对Hash进行了细分,并像这样覆盖方法[]=

def []= (key,val)
  super(key,val)
  puts 'do something'
end

但是当我拨打merge时,它无效。这样做的正确方法是什么?我是否必须覆盖更新哈希的每个方法?

2 个答案:

答案 0 :(得分:2)

由于您不关心性能,您可以将冻结的哈希包装并委托给包装的冻结实例所有方法(抢救,报告和更新另一个副本。)在这里:

class MyHash < BasicObject
  def initialize(hash = {})
    hash! hash
  end

  def hash!(hash)
    @hash = hash.freeze
  end

  def method_missing(m, *args, &λ)
    hash.send(m, *args, &λ)
  rescue => e
    raise e unless e.message.ends_with?('frozen Hash')

    # modification attempt was made
    puts 'do something'
    hash!(@hash.dup.send(m, *args, &λ)
  end
end

未经测试,但你明白了。

答案 1 :(得分:0)

请记住返回访问的值,并覆盖merge方法:

def []= (key,val)
  out = super(key,val)
  puts 'do something'
  out
end

def merge(hash)
  out = super
  puts 'do something'
  out
end

请考虑使用其他解决方案,因为moneky-patching核心类是一种可怕的做法,可能导致未定义的行为(如merge方法失败)。

尝试使用继承:

class MyHash < Hash
  def []= (key,val)
    out = super(key,val)
    puts 'do something'
    out
  end

  def merge(hash)
    out = super(hash)
    puts 'do something'
    out
  end
end

# Usage
hash = MyHash.new
hash['a'] = 42 # prints 'do something'

要获得更优雅的解决方案,您可能需要查看hooks gem。