How to enhance attr_accessor in ruby?

断了今生、忘了曾经 提交于 2019-12-24 02:23:31

问题


I want to implement a (class) method attr_accessor_with_client_reset, which does the same thing as attr_accessor, but on every writer it additionally executes

@client = nil

So, for example,

attr_accessor_with_client_reset :foo

should produce the same result as

attr_reader :foo

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

How do I achieve this?


回答1:


Sergio's solution is good, but needlessly complex: there's no need to duplicate the behavior of attr_reader, you can just delegate to it. And there's no need for all this double module include hook hackery. Plus, attr_accessor takes multiple names, so attr_accessor_with_client_reset should, too.

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



回答2:


It's actually pretty straightforward if you have some experience in ruby metaprogramming. Take a look:

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

If this code is not completely clear to you, then I strongly recommend this book: Metaprogramming Ruby.



来源:https://stackoverflow.com/questions/10410391/how-to-enhance-attr-accessor-in-ruby

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!