Ruby mixing and inheritance injection

I need to introduce callbacks in each child class of the parent class. Thus, the callback method should be called first, and the entire existing chain later:

you can achieve the thought of alias_method (or alias_method_chain):

module ChildMod1 def save puts "save ChildMod1" super end end module ChildMod2 def save puts "save ChildMod2" super end end class Parent def save puts "save Parent" end end class Child < Parent include ChildMod1 include ChildMod2 def save puts "save Child" super end alias_method :old_save, :save module_eval <<-R def save puts "save Callback" old_save end R end c = Child.new c.save 

output

 save Callback save Child save ChildMod2 save ChildMod1 save Parent 

but is it possible to achieve this through inheritance? as in ChildMod1 or ChildMod2. I want to execute code inside the module space to get all the benefits of inheritance

 module ChildMod1 def save puts "save ChildMod1" super end end module ChildMod2 def save puts "save ChildMod2" super end end class Parent def save puts "save Parent" end end class Child < Parent include ChildMod1 include ChildMod2 def save puts "save Child" super end module_eval <<-R def save puts "save Callback" super end R end c = Child.new c.save 

Output

 save Callback save ChildMod2 save ChildMod1 save Parent 

as you see, it just overwrites Child

UPDATE The wdebeaum solution is fine, but what if I need to create many methods dynamically thought out by module_eval or analog and redefine them inside the class? I can not create a separate module for them.

 class TestEval def redefine_me puts "Test method" super # I expect that it will call Eval method, but module_eval just overwrite it end module_eval <<-R def redefine_me puts "Eval method" end R end 

UPDATE2 using a singleton class, I get the wrong chain Eval => Test instead of Test => Eval

 class TestEval def initialize class << self def redefine_me puts "Eval method" super end end end def redefine_me puts "Test method" end end TestEval.new.redefine_me 

Suppose I have a โ€œmethodโ€ of a class method that adds some instance methods to Datastream (for example, it will add setter and getter methods), and I want to override one of these methods, for example:

 class Datastream field :name def name=(value) puts "redefined!" super end end 
+4
source share
1 answer

You can put the callback method in your own module and rewrite the parent initialization method to extend this module (using alias_method if necessary). This will bring the callback method to the Child method, associating it with each single Child instance class. Just remove the module_eval part from the second code example and add this to c = Child.new :

 module Callback def save puts "save Callback" super end end class Parent alias_method :old_initialize, :initialize def initialize old_initialize extend Callback end end 

Output:

 save Callback save Child save ChildMod2 save ChildMod1 save Parent 
+2
source

All Articles