rails - type variable ruby
¿Por qué el módulo `ClassMethods` definido y extendido en el mismo espacio de nombres? (2)
Mirando más en el repo hay otra clase Github::API
. Esta clase parece requerir la funcionalidad del módulo Github::ClassMethods
.
module Github
# Core class responsible for api interface operations
class API
extend Github::ClassMethods
Así que tiene sentido que sea su propio módulo. Da la posibilidad de importar solo esos métodos. Si se incluyeran los métodos de la class << self
, estarían disponibles, lo que probablemente no se desee.
Es posible que haya sido mejor tener el módulo en su propia clase o que haya nombrado otra cosa. Pero supongo que es solo una elección personal.
Estoy tratando de entender el código de github repo . Es el módulo principal de la gema para configurar el cliente.
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
- ¿Por qué se utiliza
class << self
y elmodule ClassMethods
, y luego se extiende en lugar de ser incluido en laclass << self
part? - Hay un método de clase
def included(base)
. Esto parece agregar los métodos de clase en un objeto específico. ¿Por qué es como este? Podría estar relacionado con la funcionalidad de la clase, pero no lo entiendo.
module MyModule
class << self
def included(base)
base.extend ClassMethods # what would this be for?
end
<...>
end
<...>
end
Esta es en realidad una práctica bastante común en Ruby. Básicamente, lo que dice es: cuando se realiza algún objeto include MyModule
, haz que también extend MyModule::ClassMethods
. Tal hazaña es útil si desea una combinación que agregue algunos métodos no solo a las instancias de una clase, sino a la clase en sí.
Un breve ejemplo:
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}"
# Calling the class method from the module here!
p2 = P.factory(10)
puts "#{p2.sum} #{p2.mul}"