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
class << self
and module ClassMethods
used, and then extended instead of being included in the class << self
part?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.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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With