Module: Schlepper::AbstractMethodHelper::ClassMethods
- Defined in:
- lib/schlepper/abstract_method_helper.rb
Instance Method Summary collapse
- #__abstract_methods__ ⇒ Object
-
#abstract(method_name) ⇒ Symbol
Marks a method as ‘abstract’.
-
#inherited(subclass) ⇒ Object
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.
- #method_added(method_name) ⇒ Object
Instance Method Details
#__abstract_methods__ ⇒ Object
16 17 18 |
# File 'lib/schlepper/abstract_method_helper.rb', line 16 def __abstract_methods__ @__abstract_methods__ end |
#abstract(method_name) ⇒ Symbol
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.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# 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 = ( 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, end end method_name end |
#inherited(subclass) ⇒ Object
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.
24 25 26 27 |
# 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) ⇒ Object
86 87 88 89 90 91 92 93 94 |
# 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 |