# Ancestor paths

**URL:** <https://www.ruby-forum.com/t/ancestor-paths/127881>\
**Category:** Ruby\
**Created:** [February 2, 2008, 1:52am UTC](https://www.ruby-forum.com/t/ancestor-paths/127881 "2008-02-02T01:52:32Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![pedz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/839c29/32.png) [@pedz](https://www.ruby-forum.com/u/pedz)\
**Post date:** [February 2, 2008, 1:52am UTC](https://www.ruby-forum.com/t/ancestor-paths/127881/1 "2008-02-02T01:52:32Z")

</div>

ActiveRecord does this “trick”. For a normal object, this dump  
routine:

def dump(name, obj)  
puts “#{name}'s ancestors: #{obj.class.ancestors.inspect}”  
puts “#{name}'s funky ancestors: #{(class \<\< obj; self;  
end).ancestors.inspect}”  
end

produces the same list for ancestors and funky ancestors. For an  
ActiveRecord Association, you get something like this:

temp’s ancestors: [ Cached::Queue \<snip…\>  
ActiveRecord::Locking::Pessimistic, ActiveRecord::Locking::Optimistic,  
ActiveRecord::Validations, Object, Socket::Constants,  
InstanceExecMethods, Base64::Deprecated, Base64, Kernel]

temp’s funky ancestors:  
[ActiveRecord::Associations::BelongsToAssociation,  
ActiveRecord::Associations::AssociationProxy, Object, Socket::Constants,  
InstanceExecMethods, Base64::Deprecated, Base64, Kernel]

Can someone tell me how this is done or point me to the code in active  
record?

Thank you very much,  
Perry

---

<div class="post-metadata">

**Author:** ![pedz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/839c29/32.png) [@pedz](https://www.ruby-forum.com/u/pedz)\
**Post date:** [February 2, 2008, 4:09am UTC](https://www.ruby-forum.com/t/ancestor-paths/127881/2 "2008-02-02T04:09:18Z")

</div>

Perry S. wrote:

> ActiveRecord does this “trick”. For a normal object, this dump  
> routine:  
> \<\>  
> Perry

FINALLY…

This simple program:

#!/usr/bin/env ruby

def dump(name, obj)  
puts “#{name}'s class: #{obj.class}”  
puts “#{name}'s ancestors: #{obj.class.ancestors.inspect}”  
puts “#{name}'s meta ancestors: #{(class \<\< obj; self;  
end).ancestors.inspect}”  
end

class Goofy  
alias\_method :proxy\_respond\_to?, :respond\_to?  
instance\_methods.each { |m| undef\_method m unless m =~  
/(^\_\_|^nil?$|^send$|proxy\_)/ }

def initialize(o)  
@target = o  
end

def respond\_to?(symbol, include\_priv = false)  
proxy\_respond\_to?(symbol, include\_priv) ||  
@target.respond\_to?(symbol, include\_priv)  
end

private

def method\_missing(method, \*args, &block)  
@target.send(method, \*args, &block)  
end  
end

g = Goofy.new(“hi”)

dump(“g”, g)

Produces this output:

g’s class: String  
g’s ancestors: [String, Enumerable, Comparable, Object, Kernel]  
g’s meta ancestors: [Goofy, Object, Kernel]

Geeze that took me a long time to figure out.

---

<div class="post-metadata">

**Author:** ![pedz](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/839c29/32.png) [@pedz](https://www.ruby-forum.com/u/pedz)\
**Post date:** [February 2, 2008, 4:15am UTC](https://www.ruby-forum.com/t/ancestor-paths/127881/3 "2008-02-02T04:15:04Z")

</div>

Perry S. wrote:

> g’s class: String  
> g’s ancestors: [String, Enumerable, Comparable, Object, Kernel]  
> g’s meta ancestors: [Goofy, Object, Kernel]

And, in my case, I added a method to String and to Object (the one in  
String was more specific). But g.meth was going to the one in Object  
instead of String. The reason is because it is not a missing method so  
it doesn’t get proxied.
