4

attr_accessor_with_client_resetと同じことを行う(クラス)メソッドを実装したいのですattr_accessorが、すべてのライターで追加で実行されます

@client = nil

したがって、たとえば、

attr_accessor_with_client_reset :foo

と同じ結果が得られるはずです

attr_reader :foo

def foo=(value)
  @foo = value
  @client = nil
end

どうすればこれを達成できますか?

4

2 に答える 2

10

Sergioのソリューションは優れていますが、不必要に複雑です。の動作を複製する必要はなく、attr_reader委任するだけです。そして、フックハッカリーを含むこのダブルモジュールすべての必要はありません。さらに、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
于 2012-05-02T12:18:49.263 に答える
1

ルビーのメタプログラミングの経験があれば、実際にはかなり簡単です。見てください:

module Ext
  def self.included base
    base.extend ClassMethods
  end

  module ClassMethods
    def attr_accessor_with_client_reset name
      define_method name do
        instance_variable_get "@#{name}"
      end

      define_method "#{name}=" do |v|
        instance_variable_set "@#{name}", v
        @client = nil
      end
    end
  end

end

class Foo
  include Ext

  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

このコードが完全に明確でない場合は、この本を強くお勧めします:メタプログラミングRuby

于 2012-05-02T08:52:50.157 に答える