pedz
February 2, 2008, 1:52am
1
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
pedz
February 2, 2008, 4:09am
2
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.
pedz
February 2, 2008, 4:15am
3
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.