Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enhance attr_accessor in ruby?

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?

like image 505
janko-m Avatar asked Dec 21 '22 22:12

janko-m


1 Answers

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
like image 140
Jörg W Mittag Avatar answered Jan 08 '23 13:01

Jörg W Mittag