Ruby for Rails p.462-464 - why include vs. extend?

Making my way through Ruby for Rails (excellent book, David), but am
puzzled by the explanation of why Rails jumps through hoops to turn
Module instance methods into class methods.

On p. 463, David represents the situation sans Rails:

module A
module M
module ClassMethods
def some_method
#…
end

def included©
c.extend(ClassMethods)
end
end
end

and then a class later that does this:

class B
include A::M
end

The goal as for M::ClassMethods to become class methods of B. Whew.

Here are my questions:

  1. Why can’t class B just extend A::m::ClassMethods? Why use include
    and therefore necessitate this whole indirect approach? Must be some
    advantage that I’m not seeing?

In other words, why couldn’t this have worked?

class B
extend A::m::ClassMethods
end

and then there’s no need M::included() needed at all?

  1. I guess because M::included() was overridden, class B did not get any
    instance methods - which I think would have normally been the case with
    an include statement. SO what if you wanted the “normal” inclusion
    behavior, but also wanted to do something “extra” when your module is
    included?

Thanks!
Jeff

On 10/16/06, Jeff C. [email protected] wrote:

   #...

class B

an include statement. SO what if you wanted the “normal” inclusion
behavior, but also wanted to do something “extra” when your module is
included?

Thanks!
Jeff

  1. The reason in unification - you don’t need to remember where to use
    include and where extend, and this way you get both instance and class
    methods.

  2. overriding include should have no impact on actual method
    including. It’s just a callback. All the stuff is being done in
    append_features. (At least that’s what documentation says.)
    So either the docs are wrong, or your problem is somewhere else.

Hi –

On Mon, 16 Oct 2006, Jeff C. wrote:

  #...

class B
include A::M
end

The goal as for M::ClassMethods to become class methods of B. Whew.

Here are my questions:

  1. Why can’t class B just extend A::m::ClassMethods? Why use include
    and therefore necessitate this whole indirect approach? Must be some
    advantage that I’m not seeing?

The goal is to be able to do one “include” and have both instance
methods and class methods added to the class that’s doing the
including.

In other words, why couldn’t this have worked?

class B
extend A::m::ClassMethods
end

and then there’s no need M::included() needed at all?

You’d have to do:

class B
include A::M
extend A::m::ClassMethods
end

to get the same effect.

  1. I guess because M::included() was overridden, class B did not get any
    instance methods - which I think would have normally been the case with
    an include statement. SO what if you wanted the “normal” inclusion
    behavior, but also wanted to do something “extra” when your module is
    included?

You still get the normal behavior – that is, class B will still mix
in any instance methods defined in A::M.

David

unknown wrote:

You still get the normal behavior – that is, class B will still mix
in any instance methods defined in A::M.

Got it! Sorry for my oversight.

Thanks,
Jeff