module Schlepper::AbstractMethodHelper::ClassMethods
Public Instance Methods
__abstract_methods__()
click to toggle source
@private
# File lib/schlepper/abstract_method_helper.rb, line 16 def __abstract_methods__ @__abstract_methods__ end
abstract(method_name)
click to toggle source
Marks a method as 'abstract'. That is, it is not intended to be used without overriding and implementing. Essentially re-defines the method to throw a NotImplementedError if called directly or when subclassed and not overridden. @param [String, Symbol] Name of method to mark as abstract @return [Symbol] Name of method
# File lib/schlepper/abstract_method_helper.rb, line 35 def abstract method_name # this implementation is a little long on purpose to encapsulate # all of the logic into one method. we do not want to pollute the destination # class, so no extraction techniques are available method_name = method_name.to_sym @__abstract_methods__.store method_name, true instance_eval do # undefine any existing method to prevent warnings undef_method method_name if method_defined? method_name define_method method_name do # check to see if the method we are calling is directly on the class # that implements the abstract method # # that is, if A#override_me is implemented as abstract, we want to notify the # callee that this method is abstract and can not be called directly # otherwise, we want to notify the callee that the subclass # needs to implement the abstract method before calling it # # that is, if B subclasses A and A implements override_me # as abstract, then B#override_me should notify the callee that # #override_me is declared abstract on A and needs to be overridden # on B failure_message = ( if self.class.instance_method(__method__).owner == self.class <<-MESSAGE The method #{method_name} is designated as abstract on #{self.class.name}. You must subclass #{self.class.name} and override this method yourself. MESSAGE else # now we want the inheritance chain without any inherited modules, and without # Object and BasicObject. the returned array looks like [self, D, C, B, A] # we want to notify the callee exactly where the method was declared abstract # in the chain parent_abstract_class = (self.class.ancestors - self.class.included_modules)[1..-3]. find { |klass| klass.method_defined? method_name } <<-MESSAGE The class #{self.class.name} does not implement the abstract method #{method_name}, which is declared as abstract on #{parent_abstract_class.name}. MESSAGE end ) fail NotImplementedError, failure_message end end method_name end
inherited(subclass)
click to toggle source
We want a subclass to know what is abstract or not We DO NOT want to use a class variable as they are shared from all subclasses of the base class. @private
Calls superclass method
# File lib/schlepper/abstract_method_helper.rb, line 24 def inherited subclass super subclass.instance_variable_set :@__abstract_methods__, @__abstract_methods__.dup end
method_added(method_name)
click to toggle source
@private
# File lib/schlepper/abstract_method_helper.rb, line 86 def method_added method_name # figure out if we are adding a new method from `define_method` above # we don't want to mark this is not abstract when overriding the # defined method with an abstract definition return if caller.grep(/#{__FILE__}/).grep(/define_method/).any? if @__abstract_methods__.key?(method_name) @__abstract_methods__.store method_name, false end end