Shekhar Patil
Shekhar Patil

Reputation: 337

Ruby ancestors methods issue

consider the following example:

module M
end

class C
  include M
end

c = C.new
p c.singleton_class.ancestors

the output is: [#<Class:#<C:0x000055b6b069c5f0>>, C, M, Object, Kernel, BasicObject]

but now if we include the module in singleton_class of object c as following

class << c
  include M 
  p ancestors
end

the output is: [#<Class:#<C:0x000055b6b069c5f0>>, C, M, Object, Kernel, BasicObject]

But The well-grounded Rubyist books say it should be as follows in chapter 13 Object individual:

[#<Class:#<C:0x000055b6b069c5f0>>, M, C, M, Object, Kernel, BasicObject]

Upvotes: 0

Views: 47

Answers (1)

Giuseppe Schembri
Giuseppe Schembri

Reputation: 857

To answer this question we need to understand how include works. Module#include

Invokes #append_features on each parameter in reverse order.

Module#append_features

add the constants, methods, and module variables of this module to mod if this module has not already been added to mod or one of its ancestors.

If you swap the order in which you include the module you will have the expected result

module M
end

class C
end

c = C.new

p c.singleton_class.ancestors
# -> [#<Class:#<C:0x000056285c79a678>>, C, Object, Kernel, BasicObject]
class << c
  include M 
end

p c.singleton_class.ancestors
# -> [#<Class:#<C:0x000056285c79a678>>, M, C, Object, Kernel, BasicObject]
# M is not in the ancestors of the class C is ancestors of the singleton class

class C
  include M
end

p c.singleton_class.ancestors
# -> [#<Class:#<C:0x000056285c79a678>>, M, C, M, Object, Kernel, BasicObject]
# The include statement put M as first ancestors of C

If we change the order

module M
end

class C
end

c = C.new

p c.singleton_class.ancestors
# [#<Class:#<C:0x000055b278d8a290>>, C, Object, Kernel, BasicObject]

class C
  include M
end

p c.singleton_class.ancestors
# [#<Class:#<C:0x000055b278d8a290>>, C, M, Object, Kernel, BasicObject]
# M is ancestor of C and of the singleton class #C

class << c
  include M 
end

p c.singleton_class.ancestors
# [#<Class:#<C:0x000055b278d8a290>>, C, M, Object, Kernel, BasicObject]
# M is not included

Upvotes: 1

Related Questions