我想知道,是否有一种简单的方法可以实现行为类似于ActiveModel::Dirty
的Ruby数组,所以我可以做到:
array = [1,2]
array.changed? # => false
array << 5
array.changed? # => true
到目前为止,我唯一的想法是实现TrackedArray < Array
或TrackedArray < DelegateClass(Array)
,通过Array的公共API,为每个带有感叹号的方法和其他方法(如keep_if
、<<
等)调用define_method
,并设置一个@changed_marker = true
。
这样,我将为每个数组实例获得changed? == true
,它被更改了一次,但如果在对象上撤消更改,它将不会返回到changed? == false
。因此它不能完全兼容CCD_ 10。
对于一个笨拙的实现来说,这似乎是一项巨大的努力。。。
Naiëve实现(只是出于好奇):
class Hurray
attr_accessor :dirty
def initialize *args, &cb
@array = Array.new *args, &cb
@dirty = false
end
def method_missing m, *args, &cb
@dup = @array.dup
# maybe public_send, maybe whitelist methods
@array.send(m, *args, &cb).tap do
@dirty |= @dup != @array
end
end
end
可以使attr_reader :dup
也可以在修改数组之前访问数组的最后一个副本,例如undo
。