How to hook to an Array instance in a Ruby module

On some project we needed to create a module containing an Array attribute. We wanted to hook onto some of the methods of this particular Array instance to call our own code. Here is how we did it:

module TheModule
attr_reader :items
def initialize(*args)
@items = []
def @items.<<(item)
super
"You added the item #{item} with <<!"
end
def @items.push(item)
super
"You added the item #{item} with push!"
end
super
end
end
class TheClass
include TheModule
end

And now the output:

x = TheClass.new
x.items # => []
x.items << 'blue' # => You added the item 'blue' with <<!
x.items.push 'orange' # => You added the item 'orange' with push!
x.items # => ["blue", "orange"]

5 thoughts on “How to hook to an Array instance in a Ruby module

  1. Thanks Selman, Forwardable is a pretty interesting module. Never heard about it before! But this post was about finding a way to hook to an attribute in a class and add custom code to its methods. (i.e. the “You added the item #{item} with push!” part). Not so much about making a class instance behave like some other object. But thanks for mentioning Forwardable, I have learned something!

  2. Very interesting approach!
    You could make that a little neater and better document by creating a “role” module.
    module ItemsRole
    def <<(item)
    super
    "You added the item #{item} with <<!"
    end
    def push(item)
    super
    "You added the item #{item} with push!"
    end
    end
    And then:
    @items.extend ItemsRole

Leave a Reply

Your email address will not be published. Required fields are marked *