Skip to content

Instantly share code, notes, and snippets.

@kares
Created Nov 12, 2013
Embed
What would you like to do?
#override (method) annotation for Ruby
# Allows for an #override annotation for your methods.
# Thus might help you during refactoring (method renaming) to assure methods
# expected to call a super will fail early during loading instead of runtime.
#
# Sample :
#
# class Message
# extend Override
#
# def do_send; end
# def sent_at; end
# def reply?; end
# end
#
# class Notice < Message
# override
# def do_send; super; end
#
# def reply?; nil; end
# def sent_at; nil; end
#
# override :reply?, :sent_at
# end
#
#
# Without arguments works with singleton methods as well :
#
# class Message
# extend Override
#
# def self.deliver(msg); end
# end
#
# class Notice < Message
# override
# def self.deliver(msg); end
# end
#
# To hook it up for all classes/modules, simply do a :
#
# Object.extend Override
#
# @author kares
#
module Override
Error = NoMethodError
def override(*names)
if names.empty? # next method
@_override = true
else
names.each do |name|
unless Override.overriden?(self, name)
raise Error, "previous (instance) method #{name.inspect} not found"
end
end
end
end
def method_added(name)
return super unless (@_override ||= nil); @_override = false
unless Override.overriden?(self, name, true)
raise Error, "previous (instance) method #{name.inspect} not found"
end
super
end
def singleton_method_added(name)
return super unless (@_override ||= nil); @_override = false
unless Override.overriden?(self, name, false)
raise Error, "previous singleton method #{name.inspect} not found"
end
super
end
def self.overriden?(klass, method, instance = true)
if instance
klass.included_modules.each do |mod|
return true if mod.instance_methods(true).include? method
end
return false unless klass.is_a?(Class) # "only" a Module ...
return klass.superclass.instance_methods(true).include? method
else
(class << klass; self; end).included_modules.each do |mod|
return true if mod.instance_methods(true).include? method
end
return false unless klass.is_a?(Class) # "only" a Module ...
return klass.superclass.methods(true).include? method
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment