tags:

views:

50

answers:

1
+2  Q: 

Custom << method

class Foo
  def initialize
    @bar = []
  end

  def changed_callback
    puts "Bar has been changed!"
  end

  def bar
    @bar
  end

  def bar=(a)
    @bar = a
    self.changed_callback() # (hence why this doesn't just use attr_accessor)
  end

  def bar<<(a)
    @bar.push(a)
    self.changed_callback()
  end
end

f = Foo.new()
f.bar = [1,2,3]
  => "Bar has been changed!"
f.bar << 4
  => "Bar has been changed!"
puts f.bar.inspect
  => [1,2,3,4]

Is anything like that possible?

Thanks!

+1  A: 

You need to somehow extend the object returned by Foo#bar with an appropriate #<< method. Something like this, maybe?

class Foo
  module ArrayProxy
    def <<(other)
      @__foo__.changed_callback
      super
    end
  end

  def initialize
    @bar = []
  end

  def changed_callback
    puts 'Bar has been changed!'
  end

  def bar
    return @bar if @bar.is_a?(ArrayProxy)
    @bar.tap {|bar| bar.extend(ArrayProxy).instance_variable_set(:@__foo__, self) }
  end

  def bar=(a)
    @bar = a
    changed_callback # (hence why this doesn't just use attr_accessor)
  end

end

f = Foo.new
f.bar = [1,2,3]
#  "Bar has been changed!"
f.bar << 4
#  "Bar has been changed!"
puts f.bar.inspect
#  => [1,2,3,4]
Jörg W Mittag