As you may know, when we want to enhance the functionality of a class, we usually
‘include’ or ‘extend’ it through modules which include new methods or override
existing ones.
We use ‘include’ to add Instance Methods and ‘extend’ for Class Methods.
With this in mind, we usually see things like:
#lib/posts_lib.rb
module PostsLib
module ClassMethods
def find_by_author(author)
#...
end
end
module InstanceMethods
def post_tags()
#...
end
end
def self.included base
base.send :include, InstanceMethods
base.send :extend, ClassMethods
end
end
class Post < ActiveRecord::Base
include PostsLib
end
Looking at the code, we notice that we’re overwriting the
‘self.included()’ method, which is a especial callback that is executed when the module
is included on another class (‘include PostsLib’ < Right Here).
Note, we need to use base.send :extend instead because extend is a
private method.
Just to clarify, this code will let us do things like:
@post.post_tags #instance method
Post.find_by_author 'Mumo' #class method
ActiveSupport::Concern gets rid of the self.included override altogether:
#lib/posts_lib.rb
module PostsLib
extend ActiveSupport::Concern
module ClassMethods
def find_by_author(autho)
#...
end
end
module InstanceMethods
def post_tags()
#...
end
end
end
With this, we obtain clearer code and, for example, sometimes you want to add
different code to self.included() such as logging:
def self.included base
logger.warn('Something to log here')
end
Well, that’s all, I’m still testing and learning, but i hope this will be useful to you in some way. ^^
Info source:
Better Ruby Idioms
ActiveSupport Concern
Google