#inherited
is called right after the class Foo
statement. I want something that\'ll run only after the end
statement that closes the c
No, there no such a hook to my knowledge, but the good thing is you can kind of do it yourself. Here is a possible implementation:
Is not super clean, but it works:
puts RUBY_VERSION # 2.4.1
class Father
def self.engage_super_setup(sub)
puts "self:#{self} sub:#{sub}"
sub.class_eval do
puts "toy:#{@toy}"
end
end
def self.super_setup
if self.superclass.singleton_methods.include?(:engage_super_setup)
superclass.engage_super_setup(self)
end
end
end
Son = Class.new(Father) do
@toy = 'ball'
end.tap { |new_class| new_class.super_setup } # this is needed to:
# 1. call the super_setup method in the new class.
# 2. we use tap to return the new Class, so this class is assigned to the Son constant.
puts Son.name # Son
Output:
self:Father sub:#<Class:0x0055d5ab44c038> #here the subclass is still anonymous since it was not yet assigned to the constant "Son"
toy:ball # here we can see we have acess to the @toy instance variable in Son but from the :engage_super_setup in the Father class
Son # the of the class has been assigned after the constant, since ruby does this automatically when a class is assigned to a constant
So this is obviously not as clean as a hook, but I think at the end we have a pretty good result.
If we had tried to do the same with :inherited sadly is not possible, because :inherited is called even before the execution entoer in the body of the class:
puts RUBY_VERSION # 2.4.1
class Father
def self.inherited(sub)
puts "self:#{self} sub:#{sub}"
sub.class_eval do
puts "toy:#{@toy.inspect}"
end
end
end
class Son < Father
puts "we are in the body of Son"
@toy = 'ball'
end
puts Son.name # Son
Output:
self:Father sub:Son # as you can see here the hook is executed before the body of the declaration Son class runs
toy:nil # we dont have access yet to the instance variables
we are in the body of Son # the body of the class declaration begins to run after the :inherited hook.
Son
If you are willing to assume your Ruby implements ObjectSpaces, you could could look up all model instances after the fact, and then modify them appropriately. Google suggests http://phrogz.net/ProgrammingRuby/ospace.html