🕷 zenspider.com

by ryan davis



sitemap
Looking for the Ruby Quickref?

Inherited Sucks

Published 2012-05-07 @ 17:00

Tagged thoughts, ruby

Found via a rails SNAFU:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# in rails spread across many modules and classes :(

class A
  def self.inherited(x)
    p x.instance # create a singleton upon inheritance
  end

  def self.instance
    @instance ||= new
  end

  def initialize
    p :A_initialize
  end
end

# in your application.rb

class B < A
  def initialize
    p :B_initialize
  end
end

This prints out :A_initialize only.. and is terribly confusing because it is about 8 layers of indirection deep. tenderlove and I poked at this for about 30 minutes trying to untangle why his simple initialize method wouldn’t get called.

Turns out it is that crafty instantiation inside of the inherited hook. inherited triggers on the class opening… when initialize hasn’t been defined yet.

This sucks big time and is a perfect illustration of why I think ruby needs a hook for the close of a inherited class, not just the opening. So many powerful tools could be written with such a simple hook. I have yet to see inherited be used for much more than the horrible cargo-culted ClassMethods+InstanceMethods pattern.

I found a workaround… It sucks, but it does ensure that your initialize gets called:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A
  def self.method_added m
    if self != A and m == :initialize then
      instance.send :initialize
    end
  end
end

class B < A
  def initialize
    # NEVER call super since this is instantiated through inherited :(
    p :B_initialize
  end
end