Super Blank Slates
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:
[source:ruby]
def BS(superclass = nil, name = :BlankSlate)
klass = eval(”
class #{name} #{” < #{superclass}" if superclass}
end
#{name}
")
klass.class_eval {
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
}
klass
end
[/source]
And then he came up with the anti-eval solution:
[source:ruby]
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
[/source]
refactors to:
[source:ruby]
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
[/source]
But watch out!!!:
[source:ruby]
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).
[/source]
Anyway, you get the idea, mix and match, (feedback?), whatever. Enjoy.