Created
November 12, 2013 17:14
-
-
Save kares/7434811 to your computer and use it in GitHub Desktop.
#override (method) annotation for Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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