如何增强ruby中的attr_accessor?

jan*_*o-m 2 ruby attributes metaprogramming attr-accessor

我想实现一个(类)方法attr_accessor_with_client_reset,它执行相同的操作attr_accessor,但是在它另外执行的每个编写器上

@client = nil
Run Code Online (Sandbox Code Playgroud)

所以,例如,

attr_accessor_with_client_reset :foo
Run Code Online (Sandbox Code Playgroud)

应该产生相同的结果

attr_reader :foo

def foo=(value)
  @foo = value
  @client = nil
end
Run Code Online (Sandbox Code Playgroud)

我该如何实现这一目标?

Jör*_*tag 8

塞尔吉奥的解决方案很好,但是不必要的复杂:没有必要复制行为attr_reader,你可以委托给它.并且所有这些双模块都不需要包括钩子hackery.另外,attr_accessor需要多个名字,所以也attr_accessor_with_client_reset应该这样.

module AttrAccessorWithClientReset
  def attr_accessor_with_client_reset(*names)
    attr_reader *names

    names.each do |name|
      define_method :"#{name}=" do |v|
        instance_variable_set(:"@#{name}", v)
        @client = nil
      end
    end
  end
end

class Foo
  extend AttrAccessorWithClientReset

  attr_reader :client
  def initialize
    @foo = 0
    @client = 'client'
  end

  attr_accessor_with_client_reset :foo
end

f = Foo.new
f.foo    # => 0
f.client # => "client"
f.foo = 1
f.foo    # => 1
f.client # => nil
Run Code Online (Sandbox Code Playgroud)