[英]What does #self.included(base) do in Ruby on Rails' Restful Authentication?
[英]self.included – including class methods from a module in Ruby
我读过这篇文章: Ruby模块 - 包括do end block - 但是当你在模块中使用self.included do ... end
块时仍然无法获得。
帖子说当你包含模块时,块中的代码将被运行,但是如果要包含模块的唯一目的,那么它的重点是什么? 这个代码不需要运行吗? 该块不需要存在就可以运行该代码,对吧?
下面两者之间有什么区别:
module M
def self.included(base)
base.extend ClassMethods
base.class_eval do
scope :disabled, -> { where(disabled: true) }
end
end
module ClassMethods
...
end
end
与
module M
def self.some_class_method
...
end
scope :disabled, -> { where(disabled: true) }
end
第一个代码块将ClassMethods
的类方法ClassMethods
到包含类,并在其上调用scope
方法。 第二个没有做这些事情并且会导致NoMethodError
因为模块没有scope
类方法。 包含模块后, self.some_class_method
将不会在包含类中提供。
有关模块包含如何在Ruby中工作的完整故事,请在此处阅读我的答案:
从Ruby中的modules / mixins继承类方法
self.included
如果要包含一个模块的唯一目的是什么? 包含不是模块的唯一目的。 它们还用于其他事物,例如命名空间或简单地存储可在模块本身上调用的各种类方法。
从理论上讲,Ruby 可以自动将模块中定义的所有类方法添加到包含类中,但实际上这是一个坏主意,因为您不再需要选择是否要包含类方法 - 所有类方法都将包含在每个方法中时间,无论是否打算包括在内。 考虑这个例子:
module M
def self.class_method
"foo"
end
def self.configure_module
# add configuration for this module
end
end
class C
include M
end
这里, configure_module
方法显然不应该添加到C
,因为它的目的是设置模块对象的配置。 然而,如果我们有类方法的自动包含,你将无法阻止它被包括在内。
但是所有实例方法都已包含在内! 那怎么样呢?
模块中的实例方法只有在包含在类中才真正有用 ,因为模块不能有实例,只有类可以。 因此,在一个模块中,每个实例方法都应该被包含在某个地方工作。
模块上的“类”方法是不同的,因为它可以在模块本身上调用,因此无论它是否也添加到包含类,它都可以正常使用。 这就是为什么你有一个选择更好的原因。
module M
# self.included is the hook which automatically runs when this module is included
def self.included(base)
puts 'this will be printed when this module will be included inside a class'
base.extend ClassMethods
base.class_eval do
scope :disabled, -> { where(disabled: true) }
end
end
def print_object_class
self.class.name # here self will be the object of class which includes this module
end
module ClassMethods
def print_class_name
self.name # Here self would be the class which is including this module
end
end
end
我尝试修改上面的module
以帮助您了解模块(关注点)如何在代码可重用性方面发挥作用
self.included
是一个钩子,当一个模块包含在一个类中时它会自动运行。
module ClassMethods
声明的任何方法module ClassMethods
都将成为包含此模块的类的类方法
在module ClassMethods
外部声明的任何方法module ClassMethods
将成为包含此模块的类的实例方法
对于Ex,假设有一个Product类,并且您已将模块包含在其中
class Product < ActiveRecord::Base
include M
puts 'after including M'
end
如果您在rails控制台中尝试此示例,您会注意到,只要模块M
包含在class Product
包含的模块运行挂钩中,
this will be printed when this module will be included inside a class
打印在控制台上this will be printed when this module will be included inside a class
将打印出来
在after including M
之后,这将被打印在控制台上。
您也可以尝试以下命令
Product.disabled # a scope with name 'disabled' is avaialble because of including the module M
Product.print_class_name # Outputs => 'Product' This method is available to class with the help of module M
Product.new.print_object_class #Outputs => 'Product'
它还提供可重用性,在任何类中包含此模块M,并且该类可以访问模块中描述的所有这些方法。
而你的第二个例子仅仅是基本模块的一个例子
module N
def self.abc
puts 'basic module'
end
end
现在只能使用此模块访问模块中的abc
方法定义
N.abc # outputs 'basic module'
class Product < ActiveRecord::Base
include N
end
Product.abc #raises异常,没有在类Product.new.abc #raises异常上找到的方法,没有找到类对象的方法
我希望这可以帮助您更好地理解模块的概念。 如果您还有任何疑问,请告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.