shoes/shoes — Issue #164: Multi-level inheritance from Shoes::Widget fails
Author: atownley
Created: 2011-11-19 22:19:16+00:00
State: open

I'm trying to do something similar to the following with Policeman (1739) on MacOS:

#! /usr/bin/env open -a Shoes.app

class A < Shoes::Widget; end

class B < A
def initialize(options = {}, &block)
para "B"
end
end

Shoes.app do
b
end

Doing so gives me undefined method `[]=' for nil:NilClass in shoes.rb:541:in `inherited'. The method in question looks like this:

```
535 class Types::Widget
536 @types = {}
537 def self.inherited subc
538 methc = subc.to_s[/(^|::)(\w+)$/, 2].
539 gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
540 gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase
541 @types[methc] = subc
542 Shoes.class_eval %{
543 def #{methc}(*a, &b)
544 a.unshift Widget.instance_variable_get("@types")[#{methc.dump}]
545 widget(*a, &b)
546 end
547 }
548 end
549 end
550 end
```

From looking at it, I'm guessing that the reference to @types from a class method is causing the problem. I would've thought this was a bad idea. If you change the above code to the following:

```535 class Types::Widget
536 @@types = {}
537 def self.inherited subc
538 methc = subc.to_s[/(^|::)(\w+)$/, 2].
539 gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
540 gsub(/([a-z\d])([A-Z])/,'\1_\2').downcase
541 @@types[methc] = subc
542 Shoes.class_eval %{
543 def #{methc}(*a, &b)
544 # a.unshift Widget.instance_variable_get("@types")[#{methc.dump}]
545 a.unshift Widget.class_variable_get("@@types")[#{methc.dump}]
546 widget(*a, &b)
547 end
548 }
549 end
550 end
```

It seems to work as expected. I've never messed with this part of Ruby voodoo before, so I'm not sure if this is an acceptable fix or not. However, it seems to make the above test case actually work.

Looking forward to your thoughts.