2008
04.11

So there’s BlankSlate, and today tmm1 was doing something where he was delegating to Array, but wanted to actually have Array in the ancestor chain (for Class#===), so I came up with this:

def BS(superclass = nil, name = :BlankSlate)
  klass = eval(%w[
    class #{name} #{" < #{superclass}" if superclass}
    end
    #{name}
  ])
  klass.class_eval {
    instance_methods.each { |m| undef_method m unless m =~ /^__/ }
  }
  klass
end

And then he came up with the anti-eval solution:

class BlankSlate
  instance_methods.each { |m| undef_method m unless m =~ /^__/ }
end
 
def BlankSlate superclass = nil
  if superclass
    @blank_slates ||= {}
    @blank_slates[superclass] ||= Class.new(superclass) do
      instance_methods.each { |m| undef_method m unless m =~ /^__/ }
    end
  else
    BlankSlate
  end
end

refactors to:

class BlankSlate
  instance_methods.each { |m| undef_method m unless m =~ /^__/ }
end
 
def BlankSlate superclass = BlankSlate
  @blank_slates ||= Hash.new do |h,k|
    h[k] = Class.new(superclass) do
      instance_methods.each { |m| undef_method m unless m =~ /^__/ }
    end
  end
  @blank_slates[superclass]
end

But watch out!!!:

a = StrokeDB::LazyMappingArray.new([1,2,3]) # => [1, 2, 3]
Array === a # => true
Array.new(a) # => []
[a].flatten # => []
 
# The last two are 'incorrect' behaviour (probably work on rubinius,
# mind you, so did the delegation approach).

Anyway, you get the idea, mix and match, (feedback?), whatever. Enjoy.

2008
04.11

I know, I’m shouting, but there’s stuff to shout about!

I’ve hated ri for being so slow for so long. The new one is out!

I really recommend installing rdoc 2 and firing up ri for the first time. Now only the ‘first time’ takes a long time :D

It’s joyous, just under a second I can really put up with. Thanks to Eric, and I believe Ryan (as I seem to remember him mentioning his ri patch quite some time ago). :-)