Skip to content

Instantly share code, notes, and snippets.

@glucero
Last active December 13, 2015 17:09
Show Gist options
  • Save glucero/4945872 to your computer and use it in GitHub Desktop.
Save glucero/4945872 to your computer and use it in GitHub Desktop.
module Extendable
def unique_instance_methods
instance_methods.sort - superclass.instance_methods.sort
end
def extend_methods(*methods)
methods.each do |method_extender|
method = instance_method(method_extender)
send(:define_method, method_extender) do
yield method.bind(self)
end
end
end
def printable_methods(*methods) # ^caller[3]
extend_methods(*methods) do |method| # caller[2]
method.call.tap do |response| # caller[1]
$stdout.puts "caller: #{caller[3][/`(.+)'/, 1]}" # caller[0]
$stdout.puts "method: #{method.receiver.class}##{method.name}"
$stdout.puts "response: #{response.inspect}"
end
end
end
def rescuable_methods(*methods)
extend_methods(*methods) do |method|
begin
method.call
rescue Exception => error
$stderr.puts error.message, *error.backtrace
end
end
end
def countable_methods(*methods)
send(:define_method, :method_counter) do
@method_counter ||= Hash.new(0)
end
extend_methods(*methods) do |method|
method.receiver.method_counter[method.name] += 1
method.call
end
end
def chainable_methods(*methods)
extend_methods(*methods) do |method|
method.call
method.receiver
end
end
end
class Dog
attr_reader :name, :age
def alive?
!!@age
end
def born!
@age = 0
end
def advance
@age += 1
end
def initialize(name)
@name = name
end
extend Extendable
chainable_methods :advance
countable_methods :alive?
printable_methods :name, :born!
extend_methods(:advance) do |method|
method.receiver.alive? ? method.call : raise("#{name} has not been born yet.")
end
end
@glucero
Copy link
Author

glucero commented Feb 13, 2013

spot = Dog.new('Spot')
spot.name

caller: <main>
method: Dog#name
response: "Spot"
=> "Spot"

spot.name.upcase.to_sym

caller: <main>
method: Dog#name
response: "Spot"
=> :SPOT

spot.advance

RuntimeError: Spot has not been born yet.

spot.born!

caller: <main>
method: Dog#born!
response: 0
=> 0

spot.advance.advance.advance.advance.advance

=> #<Dog:0x007fa6326c8420>

spot.method_counter

=> { :alive? => 6 }

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