# Redefining a method using Module#include

**URL:** <https://www.ruby-forum.com/t/redefining-a-method-using-module-include/75697>\
**Category:** Ruby\
**Created:** [November 12, 2006, 2:01pm UTC](https://www.ruby-forum.com/t/redefining-a-method-using-module-include/75697 "2006-11-12T14:01:44Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [November 12, 2006, 2:01pm UTC](https://www.ruby-forum.com/t/redefining-a-method-using-module-include/75697/1 "2006-11-12T14:01:44Z")

</div>

Hi,

How can I redefine Array#[] using an included Module? Here is my  
attempt:

module AbsenceHandling  
def if\_absent\_call§  
@if\_absent = p  
self  
end

```
def [](index)
    result = old_accessor(index)
    if(result.nil? && !@if_absent.nil?)
        result = @if_absent.call(index)
        self[index]=result
    end
    result
end

```

end

class Array  
alias :old\_accessor :[]  
include AbsenceHandling  
end

x = [1,2,3].if\_absent\_call(proc{|index|  
“#{index}”  
})  
puts x[5]

Thanks very much,  
Mike

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [November 12, 2006, 6:38pm UTC](https://www.ruby-forum.com/t/redefining-a-method-using-module-include/75697/2 "2006-11-12T18:38:35Z")

</div>

On 11/12/06, removed\_email\_address@domain.invalid [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> class Array  
> alias :old\_accessor :[]  
> include AbsenceHandling  
> end
> 
> x = [1,2,3].if\_absent\_call(proc{|index|  
> “#{index}”  
> })  
> puts x[5]

Hi,

If a class defines a method, it has higher precedence than methods of  
any of its included modules. So the “override” never happens in this  
case. You can work around it by defining the [] operator directly in  
Array method, via Module#included and Module#define\_method. You can  
alias the old [] in the included as well.

module AbsenceHandling  
def if\_absent\_call(p)  
@if\_absent = p  
self  
end

def self.included(base)  
# base = Array in this case  
# alias\_method and define\_method are private, so we must  
# use the send trick  
base.send(:alias\_method, :old\_accessor, :[])  
base.send(:define\_method, :[]) do |index|  
result = old\_accessor(index)  
if(result.nil? && !@if\_absent.nil?)  
result = @if\_absent.call(index)  
self[index]=result  
end  
result  
end  
end  
end

class Array  
include AbsenceHandling  
end

Note: [] in Array is a special case (as are some other methods in base  
C classes) as sometimes their C versions are called directly for the  
sake of speed. So e.g. Array#to\_s will use the old []

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [November 12, 2006, 7:16pm UTC](https://www.ruby-forum.com/t/redefining-a-method-using-module-include/75697/3 "2006-11-12T19:16:44Z")

</div>

removed\_email\_address@domain.invalid wrote:

> class Array  
> alias :old\_accessor :[]  
> include AbsenceHandling  
> end
> 
> x = [1,2,3].if\_absent\_call(proc{|index|  
> “#{index}”  
> })  
> puts x[5]

There are a number of ways. To be clear you are asking for code inject  
rather then inheritance. traditionally subclasses are used add  
functionality, But with Ruby we have the power to directly effect core  
classes. In doing so first ask yourself if you really need a module. If  
not the simple do:

class Array  
def if\_absent\_call§  
…  
alias :old\_accessor :[]  
def   
…

The next levelup gets more complicated one way is to use the #included  
callback to inject the code directly, but this is a misrepresentation  
of what include should do (i.e. inheritance) and I strong discourage  
it. Another related approach is alias\_method\_chain supported by both  
ActiveSupport and Facets. Here is an example:

```
module X
  def self.included(base)
    base.module_eval {
      alias_method_chain :foo, :feature
    }
  end
  def foo_with_feature
    foo_without_feature + '!'
  end
end

class Y
  def foo ; "FOO" ; end
  include X
end

y = Y.new
assert_equal( "FOO!", y.foo )

```

But this would be a little tricker with an operator and it also has  
it’s own downsides. Other solution you can look into are Facets’  
Module#prepend and Facets’ Cut implementation.

Having said all that, you know what you are attempting to do is  
dangerous stuff. Muckng with Array#[] may have sever side effects. In  
this case, I highly recommend using singleton instead:

a = []  
a.extend AbsenceHandling

Just replace #old\_accessor with #super. It’s a case be case basis, but  
it’s much safer and hek, it’s easy 🙂

T.
