In the following code include module is used. The way I see it if include module is removed then also an instance method would be created. Then why user include module ?
http://github.com/rails/rails/blob/master/activerecord/lib/active_record/associations.rb#L1416
include Module.new {
class_eval <<-RUBY, __FILE__, __LINE__ + 1
def destroy # def destroy
super # super
#{reflection.name}.clear # posts.clear
end # end
RUBY
}
First of all let’s make one thing clear. When they call
superinside theclass_eval— it has absolutely nothing to do with why they usedinclude Module.new {}thing. In fact thesuperwhich was called inside thedestroymethod is completely irrelevant to answering your question. There could be any arbitrary code inside that destroy method.Now that we got it out of the way, here’s what’s going on.
In ruby, if you simply define a class method, and then define it again in the same class, you will not be able to call
superto access the previous method.For example:
This makes sense, because the first
foowas not defined in some superclass, or anywhere up the lookup chain (which is wheresuperpoints). However, you can define the firstfooin such a way that when you later overwrite it — it will be available by callingsuper. This is exactly what they wanted to achieve with doing module include.This works, because when you include a module, ruby inserts it into the lookup chain. This way you can subsequently call
superin the second method, and expect the included method to be called. Great.However, you may wonder, why not simply include a module without all the tricks? Why are they using block syntax? We know that my above example is exactly equivalent to the following:
So why didn’t they do that? The answer is — the call to
reflection. They needed to capture the variable (or method) which was available in the current context, which isreflection.Since they are defining the new module using block syntax, all the variables outside of the block are available for usage inside the block. Convenient.
Just to illustrate.
Neat, huh?
Now let me stress it again. The call to
superinside of thedestroymethod in your example has nothing to do with any of the above. They called it for their own reasons, because maybe the class where this is happening is subclassing another class which already defineddestroy.I hope this made it clear.