Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the module `ClassMethods` defined and extended in the same namespace?

Tags:

I am trying to understand code from github repo. It's the main module of the gem to setup the client.

module Github   # more code   class << self     def included(base)       base.extend ClassMethods # what would this be for?     end     def new(options = {}, &block)       Client.new(options, &block)     end     def method_missing(method_name, *args, &block)       if new.respond_to?(method_name)         new.send(method_name, *args, &block)       elsif configuration.respond_to?(method_name)         Github.configuration.send(method_name, *args, &block)       else         super       end     end     def respond_to?(method_name, include_private = false)       new.respond_to?(method_name, include_private) ||       configuration.respond_to?(method_name) ||       super(method_name, include_private)     end   end    module ClassMethods     def require_all(prefix, *libs)       libs.each do |lib|         require "#{File.join(prefix, lib)}"       end     end     # more methods ...   end    extend ClassMethods   require_all LIBDIR,     'authorization',     'validations',     'normalizer',     'parameter_filter',     'api',     'client',     'pagination',     'request',     'response',     'response_wrapper',     'error',     'mime_type',     'page_links',     'paged_request',     'page_iterator',     'params_hash'  end 
  1. Why is class << self and module ClassMethods used, and then extended instead of being included in the class << self part?
  2. There is a class method def included(base). This seems to add the class methods into a specific object. Why is it like this? It could relate to the functionality of the class, but I do not understand it.
like image 212
Ryan-Neal Mes Avatar asked Jun 10 '15 12:06

Ryan-Neal Mes


People also ask

How modules work in Ruby?

A Ruby module is nothing more than a grouping of objects under a single name. The objects may be constants, methods, classes, or other modules. Modules have two uses. You can use a module as a convenient way to bundle objects together, or you can incorporate its contents into a class with Ruby's include statement.

What is a Ruby namespace?

Namespace in Ruby allows multiple structures to be written using hierarchical manner. Thus, one can reuse the names within the single main namespace. The namespace in Ruby is defined by prefixing the keyword module in front of the namespace name. The name of namespaces and classes always start from a capital letter.


1 Answers

module MyModule   class << self     def included(base)       base.extend ClassMethods # what would this be for?     end     <...>   end   <...> end 

This is actually a pretty common practice in Ruby. Basically, what it's saying is: when some object performs include MyModule, make it also extend MyModule::ClassMethods. Such a feat is useful if you want a mixin that adds some methods not just to the instances of a class, but to the class itself.

A short example:

module M   # A normal instance method   def mul     @x * @y   end     module ClassMethods     # A class method     def factory(x)       new(x, 2 * x)     end   end     def self.included(base)     base.extend ClassMethods   end end   class P   include M   def initialize(x, y)     @x = x     @y = y   end     def sum     @x + @y   end end   p1 = P.new(5, 15) puts "#{p1.sum} #{p1.mul}" # <= 20 75  # Calling the class method from the module here! p2 = P.factory(10) puts "#{p2.sum} #{p2.mul}" # <= 30 200 
like image 98
art-solopov Avatar answered Sep 22 '22 05:09

art-solopov