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.
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.
‘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).
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
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!!
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
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.