# Weird binding error

**URL:** <https://www.ruby-forum.com/t/weird-binding-error/127718>\
**Category:** Ruby\
**Created:** [January 31, 2008, 6:33pm UTC](https://www.ruby-forum.com/t/weird-binding-error/127718 "2008-01-31T18:33:17Z")\
**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:** [January 31, 2008, 6:33pm UTC](https://www.ruby-forum.com/t/weird-binding-error/127718/1 "2008-01-31T18:33:17Z")

</div>

# Below is code that represents the code I am working on. The line

# that reads temp.wrap\_with\_combined is the problem. I am not sure if

# this is a bug in my brain, Rails, or Ruby. And, I’m stumped as to

# how to continue to debug it.

# 

# At the point temp.wrap\_with\_combined is called, temp is a

# Cached::Queue according to the dump\_me output. The dump\_me code and

# its output are included here. According to the debugging output,

# temp is a Cached::Queue but instead of calling wrap\_with\_combined in

# Cached::Queue or Cached::Base, it calls wrap\_with\_combined in

# Object. I can see this from the debug output.

# 

# I’ve tried moving the def of wrap\_with\_combined in Cached::Base so

# it gets defined when the subclass is defined. I’ve tried many

# things but it always ends up calling Object#wrap.

# 

# Another clue is, I replace the temp.wrap call with this:

# dump\_me(temp)

# m = temp.class.instance\_method(:wrap\_with\_combined)

# m.bind(temp).call

# 

# But I get this error:

# ActionView::TemplateError (bind argument must be an instance of

Cached::Queue) on line #6 of retain/favorite\_queues/new.html.erb:

# 

# So, while the debug says I have a Cached::Queue, the internals of

# Ruby say that I do not.

# 

# I’ve tried to make a simple testcase to show this but I have not

# been able to. If ActiveRecord::Base is replaced with a simple base,

# the problem goes away. Or if the Cached::Queue is created directly,

# the problem goes away.

# 

# Any ideas?

# 

class Object  
def wrap\_with\_combined  
logger.debug “Object wrap returns self”  
self  
end  
end

class Cached::Base \< ActiveRecord::Base  
def wrap\_with\_combined  
logger.debug “Cached::Base wrap returns wrapped object”  
wrap\_object(self)  
end

def self.inherited(subclass)  
super(subclass)  
subclass.class\_eval {  
def wrap\_with\_combined  
logger.debug “Alternate place to put wrap.”  
logger.debug “Cached::Base wrap returns wrapped object”  
wrap\_object(self)  
end  
}  
end  
end

class Cached::Queue \< Cached::Base

# …

end

class WrappedBase  
def self.inherited(subclass)  
super(subclass)  
subclass.class\_eval {  
# Define getter methods for each association  
db\_associations.each do |name|  
eval(“def #{name}  
temp = @cached.#{name}  
unless temp && cache\_valid  
call\_load  
temp = @cached.#{name}  
end  
dump\_me(temp)  
# Problem occurs here wrap calls Object#wrap instead  
# of Cached::Base#wrap or Cached::Queue#wrap  
temp.wrap\_with\_combined  
end”, nil, **FILE** , **LINE** )  
end

```
  def dump_me(obj)
    klass = obj.class
    return if klass.nil?
    logger.debug("DMP: 1 class=#{klass} name=#{klass.name}

```

methods=#{klass.instance\_methods(false).inspect}")  
klass = klass.superclass  
return if klass.nil?  
logger.debug(“DMP: 2 class=#{klass} name=#{klass.name}  
methods=#{klass.instance\_methods(false).inspect}”)  
klass = klass.superclass  
return if klass.nil?  
logger.debug(“DMP: 3 class=#{klass} name=#{klass.name}  
methods=#{klass.instance\_methods(false).inspect}”)  
klass = klass.superclass  
return if klass.nil?  
logger.debug(“DMP: 4 class=#{klass} name=#{klass.name}  
methods=#{klass.instance\_methods(false).inspect}”)  
klass = klass.superclass  
return if klass.nil?  
logger.debug(“DMP: 5 class=#{klass} name=#{klass.name}  
methods=#{klass.instance\_methods(false).inspect}”)  
end  
}  
end  
end

class WrappedQueue \< WrappedBase

# …

end

# DMP: 1 class=Cached::Queue name=Cached::Queue

methods=[“wrap\_with\_combined”, “favorite\_queues”, “favorite\_queue\_ids”,  
“favorite\_queues=”, “calls”, “call\_ids”, “favorite\_queue\_ids=”,  
“validate\_associated\_records\_for\_favorite\_queues”, “calls=”,  
“call\_ids=”, “validate\_associated\_records\_for\_calls”]

# DMP: 2 class=Cached::Base name=Cached::Base methods=[“to\_combined”]

# DMP: 3 class=ActiveRecord::Base name=ActiveRecord::Base

methods=[“to\_param”, “increment”, “readonly!”, “allow\_concurrency”,  
“destroy”, “default\_timezone”, “record\_timestamps”, “quoted\_id”,  
“reload”, “save\_without\_transactions”, “save!”, “update\_attributes”,  
“valid?”, “update\_attributes!”, “verification\_timeout”,  
“attributes\_before\_type\_cast”, “colorize\_logging”, “new\_record?”,  
“logger”, “id\_before\_type\_cast”, “save\_without\_transactions!”, “eql?”,  
“toggle!”, “pluralize\_table\_names”, “valid\_without\_callbacks?”, “id”,  
“[]”, “attribute\_present?”, “inspect”, “column\_for\_attribute”, “[]=”,  
“save\_without\_validation”, “decrement!”, “update\_attribute”, “frozen?”,  
“id=”, “hash”, “update\_attribute\_without\_validation\_skipping”,  
“table\_name\_suffix”, “connection”, “configurations”,  
“save\_without\_validation!”, “toggle”, “becomes”, “attribute\_names”,  
“readonly?”, “clone”, “increment!”, “attribute\_for\_inspect”,  
“attribute\_types\_cached\_by\_default”, “table\_name\_prefix”, “attributes”,  
“freeze”, “save”, “schema\_format”, “decrement”,  
“destroy\_without\_callbacks”, “==”, “has\_attribute?”, “attributes=”,  
“primary\_key\_prefix\_type”, “lock\_optimistically”,  
“destroy\_without\_transactions”]

# DMP: 4 class=Object name=Object methods=[“subclasses\_of”,

“require\_or\_load”, “require”, “to\_yaml\_style”, “wrap\_with\_combined”,  
“with\_options”, “require\_association”, “copy\_instance\_variables\_from”,  
“to\_yaml\_properties”, “duplicable?”, “instance\_exec”, “load”,  
“unloadable”, “taguri”, “to\_json”, “blank?”, “require\_dependency”,  
“to\_query”, “instance\_values”, “dclone”, “remove\_subclasses\_of”,  
“extend\_with\_included\_modules\_from”, “taguri=”, “to\_yaml”, “`”,  
“to\_param”, “returning”, “extended\_by”, “unwrap\_to\_cached”, “send!”,  
“acts\_like?”]

---

<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:** [January 31, 2008, 7:13pm UTC](https://www.ruby-forum.com/t/weird-binding-error/127718/2 "2008-01-31T19:13:01Z")

</div>

On Jan 31, 2008, at 10:33 AM, Perry S. wrote:

> ```
> # Problem occurs here wrap calls Object#wrap instead
> # of Cached::Base#wrap or Cached::Queue#wrap
> temp.wrap_with_combined
> 
> ```

there really isn’t enough code there to say, but i’m guessing you have  
a ‘has\_many’ association and are calling ‘wrap\_with\_combined’ on a  
_Array_, thus defining it on Object intercepts this call.

perhaps an explanation of what you are trying to do?

regards.

a @ [http://codeforpeople.com/](http://codeforpeople.com/)

---

<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 1, 2008, 5:41am UTC](https://www.ruby-forum.com/t/weird-binding-error/127718/3 "2008-02-01T05:41:52Z")

</div>

ara howard wrote:

> On Jan 31, 2008, at 10:33 AM, Perry S. wrote:
> 
> > ```
> > # Problem occurs here wrap calls Object#wrap instead
> > # of Cached::Base#wrap or Cached::Queue#wrap
> > temp.wrap_with_combined
> > 
> > ```
> 
> there really isn’t enough code there to say, but i’m guessing you have  
> a ‘has\_many’ association and are calling ‘wrap\_with\_combined’ on a  
> _Array_, thus defining it on Object intercepts this call.
> 
> perhaps an explanation of what you are trying to do?
> 
> regards.
> 
> a @ [http://codeforpeople.com/](http://codeforpeople.com/)

Thanks Howard.

I found a way to dump out ancestors and I found a thread talking about  
association proxies. In that thread, it tells to do (from memory) (  
class \<\< temp; self; end).ancestors

Doing this produces a list of associations and proxies, etc (as you  
predicted). And Cached::Queue is not in the list.

I added wrap and unwrap methods to a couple of the association classes  
and that solved my problem. I am not yet to what I think is a general  
solution but I’m at least understanding what is happening at little  
more.

What am I doing? I have a legacy system that is remote called Retain.  
For each concept, like a PMR, I have three classes. Retain::PMR,  
Cached::PMR, and Combined::PMR. Retain::PMR goes to retain and gets the  
data. Cached::PMR is a subclass of ActiveRecord::Base and uses all the  
normal ActiveRecord features. Combined::PMR is the magic that glues  
them together. For any request, I look to see if I have it in  
Cached::PMR. I use time stamps to expire it, etc. If it is there and  
current, I just present that. If not, I go to Retain::PMR to get the  
data from Retain and save it in Cached::PMR. All the usual rails code  
(the controllers and views) work with Combined objects (or thats the  
idea).

Most of the magic is done with method\_method and respond\_to? so when  
pmr.owner comes, it goes to a Combined instance’s method\_missing which  
(if the cache is deemed valid) is forwarded on to the Cached  
(ActiveRecord) instance. When the request completes, it is “wrapped” so  
the result is a Combined instance – not a Cached instance.

Most things, the “wrapped” version is self. For instances of bases  
which are a subclass of Cached::Base, the wrapped version is the  
equivalent Combined version. For somethings like Arrays and Hash, the  
wrap version is an Arrary or Hash with each value wrapped.

Right now, my biggest question is how does the association do this  
magic? I haven’t found it yet. Driving home I thought I need to look  
for places that do things like class \<\< self and other things like that  
which modify the metaclass of an object. I’ve been looking at  
initialize and those things but that hasn’t told me anything. But I’m  
wondering how an object that isn’t an Array (to pick an example) says  
“Array#…” when inspected or when name is called, etc.

Thank you for your help
