Skip to content

Instantly share code, notes, and snippets.

@Phrogz
Created November 9, 2010 19:52
Show Gist options
  • Save Phrogz/669692 to your computer and use it in GitHub Desktop.
Save Phrogz/669692 to your computer and use it in GitHub Desktop.
Temporarily tweak classes to use new methods; idea (and necessary 'remix' functionality) stolen from banister(fiend)
# gem install remix; needed to uninclude modules
require 'remix'
class Class
@tweaks = Hash.new{ |h,k| h[k]=Hash.new{ |h,k| h[k] = Module.new } }
class << self; attr_reader :tweaks; end
def when_tweaked_as(name,&block)
Class.tweaks[name][self].class_eval(&block)
end
def apply_tweak(name,mod=nil)
mod ||= Class.tweaks[name][self]
include mod
end
def remove_tweak(name,mod=nil)
mod ||= Class.tweaks[name][self]
uninclude mod # needs 'remix' gem
end
end
module Kernel
def apply_tweak(name)
Class.tweaks[name].each{ |const,mod| const.apply_tweak(name,mod) }
end
def remove_tweak(name)
Class.tweaks[name].each{ |const,mod| const.remove_tweak(name,mod) }
end
def using_tweak(name)
begin
apply_tweak(name)
yield
ensure
remove_tweak(name)
end
end
end
if __FILE__==$0 then
class String
when_tweaked_as(:swizzlers) do
def swizzle; reverse; end
end
when_tweaked_as(:gerdunken) do
def thunk; raise "NO THUNKING"; end
end
end
class Integer
when_tweaked_as(:swizzlers) do
def swizzle; to_s.reverse.to_i; end
end
end
p "foo".swizzle rescue p "NO String#swizzle before"
p "foo".thunk rescue p "NO String#thunk before"
p 24.swizzle rescue p "NO Integer#swizzle before"
using_tweak :swizzlers do
p "foo".swizzle rescue p "NO String#swizzle during"
p "foo".thunk rescue p "NO String#thunk during"
p 24.swizzle rescue p "NO Integer#swizzle during"
end
p "foo".swizzle rescue p "NO String#swizzle after"
p "foo".thunk rescue p "NO String#thunk before"
p 24.swizzle rescue p "NO Integer#swizzle after"
#=> "NO String#swizzle before"
#=> "NO String#thunk before"
#=> "NO Integer#swizzle before"
#=> "oof"
#=> "NO String#thunk during"
#=> 42
#=> "NO String#swizzle after"
#=> "NO String#thunk before"
#=> "NO Integer#swizzle after"
end
@banister
Copy link

very cool, nice work, though i find the when_tweaked_as syntax inside Integer and so on a tiny bit jarring, but it's perhaps because im not used to it yet. I am currently aiming for the current syntax:

tweak :MyTweaks do
  class String
    def hello; :hello; end
  end

  class Fixnum
    def bye; :bye; end
  end
end

using :MyTweaks do
  "john".hello #=> :hello
  5.bye #=> :bye
end

Cheers :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment