Self.included question

Hi there,

I see the following code chunk in a lot of Rails plugins:

def self.included(base)
base.extend(ClassMethods)
end

module ClassMethods
def method_one
end

 def method_two
 end

end

I’m most curious about “self.included”. I checked out the docs on
‘included’
(http://www.ruby-doc.org/core/classes/Module.html#M001661). They pointed
to
‘Module.append_features’ (
class Module - RDoc Documentation). Even after
reading the docs, I’m still a little lost. Could someone break it down a
little more than the docs? …or point me at some other resource. I’d
like
to know “why” this is done.

Thanks,
Dave

On 5/16/07, Dave H. [email protected] wrote:

 end

 def method_two
 end

end

I’m most curious about “self.included”. I checked out the docs on ‘included’
(class Module - RDoc Documentation).
This is the doc about #include not #included!!
They pointed to
‘Module.append_features’ (
class Module - RDoc Documentation). Even after
reading the docs, I’m still a little lost. Could someone break it down a
little more than the docs? …or point me at some other resource. I’d like
to know “why” this is done.

Thanks,
Dave

The included hook is run whenever a module is included.
The parameter base passed to the hook is referring to the class into
which the module is included.
Basically
def self.included(base)
base.extend(ClassMethods)
end
means:
and if you include me you also extend your class to all methods
defined in ClassMethods.

This means that instead of writing

class X
include Y
extend ClassMethods
end

you write
class X
include Y # ==> the hook does X.extend(ClassMethods)
end

Although I do not know Rails it might be a reasonable guess that the
functionality of ClassMethods is closely coupled with the
functionality of the inserted module - and that methods of the module
need class methods from ClassMethods.

HTH
Robert

On May 16, 2007, at 10:02 PM, Dave H. wrote:

end

‘Module.append_features’ (
class Module - RDoc Documentation). Even after
reading the docs, I’m still a little lost. Could someone break it
down a
little more than the docs? …or point me at some other resource.
I’d like
to know “why” this is done.

If a module implements self.included the interpreter calls that
method whenever the module is included in another module or class,
which is passed as its single argument.

Object#extend on the other hand adds the instance methods of the
module or modules passed as arguments to the target object (as
singleton methods). If the object is a class, that means you are
making module instance methods available as class methods in that
class, and that’s what base is when a module is being included in a
class.

In short, plugins put methods that will end up being class methods
(acts_as_something, say) in their own nested module, conventionally
called ClassMethods, and then include them in init.rb. For instance

ActiveRecord::Base.send(:include, MyModule)

That triggers inclusion when Rails boots, so your code is able to
call those class methods as if they belonged to the original API of
ActiveRecord::Base (in the example).

– fxn

Robert D. schrieb:

I’m most curious about “self.included”. I checked out the docs on
‘included’
(class Module - RDoc Documentation).
This is the doc about #include not #included!!

You are looking for the wrong Method - see documentation about
“Object#extend”.
The usages are visible in the example:

module ClassMethods
def method_one
puts “in method_one”
end

def method_two
puts “in method_two”
end
end

def incl1(x)
x.extend(ClassMethods)
end

module Mymod
def self.incl2(x)
x.extend(ClassMethods)
end
end

incl1(String)
Mymod.incl2(Array)

String.method_one # => in method_one
String.method_two # => in method_two

Array.method_one # => in method_one
Array.method_one # => in method_one

Wolfgang Nádasi-Donner

Robert and Xavier (fxn) -

Thank you for the explanations! That just cleared things up
tremendously.

So say I have this module (rails plugin):

module Office
def self.included(base)
base.extend(ClassMethods)
end

module ClassMethods
def working(options={})
# do something based off the options
end
end

end

In one of my models I can then access the method ‘working’ by:

class ModelName < ActiveRecord::Base
working :task => “Take a break!”
end

Thanks again

-Dave

On 5/16/07, Dave H. [email protected] wrote:

end

In one of my models I can then access the method ‘working’ by:

class ModelName < ActiveRecord::Base

#given that you include Office before
include Office

working :task => “Take a break!”
end

Thanks again

-Dave
Cheers
Robert

On 5/16/07, Wolfgang Nádasi-Donner [email protected] wrote:

Robert D. schrieb:
No it was not me, it was OP!

I’m most curious about “self.included”. I checked out the docs on
‘included’
(class Module - RDoc Documentation).
This is the doc about #include not #included!!

Robert

On May 16, 2007, at 10:39 PM, Dave H. wrote:

end

class ModelName < ActiveRecord::Base
working :task => “Take a break!”
end

Exactly.

In regular Ruby you’d need to include Office by hand in the model
class, but in Rails it is normal (I’d say even expected) that the
plugin does the include in AR::Base for you in init.rb using the
idiom mentioned in the previous post.

– fxn