文章转载自
http://consy.blog.51cto.com/2212530/399959
Ruby中Class,Object,Module这三个类定义了一些回调方法,这些方法不是默认的不过为一个类模块获对象定义了这些方法,当特定的事件发生时,将调用这些回调和钩子方法。这些回调方法一般以"ed"结尾。特定事件是指:
调用一个不存的对象方法(method_missing)
模块被混含(included/extended)
类被继承(inherited)
类或模块定义实例方法(method_added)
对象新增加一个单例方法(singleton_method_added)
实例方法被删除或取消(method_removed/method_undefined)
对象的单例方法被取消或被取消(singleton_method_removed/singleton_undefined)
引用一个不存在的常量(const_missing)
以上每一个事件对应的方法被定义了,当事件发生时,这些方法将会被调用。
method_missing
给对象调用一个方法,对象未定义,则会抛出NoMethodError异常,这时就可以使用method_missing来拦截,该方法接受为一个一个参数,即被调用的未定义方法的方法名。
class C
def method_missing(m)
puts "There's no method called #{m} here -- please try again."
end
end
C.new.anything
这里就会调用method_missing方法。
method_missing是一个有用的工具,在所有Ruby标准的钩子方法和回调方法中,是使用最广泛的一个回调方法。
Module#included
当一个模块混入到类时,如果该模的included方法已经定义,那么该方法被调用。该方法的唯一参数就是接受混含的类的名字。
module M
def self.included(c)
puts "I have justbeen mixed into #{c}."
end
end
class C
include M
end
混含模块到类中使得在模块中的所有实例方法可以被作为类的实例的方法。如果在混含模块时要给包含此模块的类添加类方法不能采用形如:def self.method_name end形式,可以用included回调方法。
用included可以捕获混含操作,并以此给混含模块的类添加类方法:
module M
def self.included(c)
def c.a_class_method
puts "Now the class has a new class method."
end
end
end
class C
include M
end
c = C.new
C.a_class_method
输出结果:
Now the class has a new class method.
由于C做为included的唯一参数传入到c,接着定义了c.a_class_method就相当于是给类C定义了类方法,extended方法与此类似。
有的人喜欢以此种方式给模块添加实例及类方法:
在这之前不得不说说include与extend的区别。include是个私有方法,顾名思义是包含的意思,也即把模块中的方法包含进来。在ruby中方法都是存储在类中的,一个对象调用一个方法是在所属类的继承链中由近及远(包括单例类)的寻找,直到找到为止。所以include方法只能由类对象来本身来调用,而不能由普通实例(因为其实包括Class类在内的所有类都是Class类的实例,所以我称类这种特殊的对象为类对象),并且include方法是私有的,所以只能在类中隐式调用。正因为ruby中方法是保存在类中,所以也只能由类包含(include)方法了。而类调用include的结果是产生了一个委托类,作为调用include方法的这个类的直接父类。而原来模块中的方法,都会塞到委托类中而被此类继承成为实例方法。
而extend顾名思义,是拓展的意思,即拓展一个对象。因为类也是对象,所以类对象,普通对象都可以调用这个extend,也即extend是个public方法。我们知道拓展一个对象就是往这个对象的单例类中塞东西,包括类对象在内的每个对象都可以有一个单例类,单例类会成为原先产生这个对象的那个类的直接子类,但是单例类是匿名的并且对外部是透明的。extend一个模块,就是把一个模块中的方法塞到这个对象的单例类中。当一个类对象调用extend方法时,模块中的方法就会变成类对象的单例类中的实例方法,既然是类对象所属的单例类中的方法,那就由类直接调用咯,既然是由类直接调用那么也就是类方法了。其实类方法也没有太多神奇的地方,也是实例方法。前面说过方法都是存储在类中的,那类方法呢?因为类也是对象,所以类方法也是存储在类中,只不过存储在类对象的单例类中。我们知道所有的类都是Class类(当然也包括Class对象本身)的实例,那么类的单例类就会变成Class类的直接子类,只不过类的单例类有些特殊之处就是类的单例类之间会保持原来类的继承性,即如果原来两个类有继承关系,那么这两个类的单例类也会有相应的继承关系,当然这一切对外部而言还是透明的。
module M
self.included(recipient)
recipient.extend(ModuleClassMethods)
recipient.class_eval do
include ModuleInstanceMethods
end
end
module ModuleClassMethods
#定义类方法
end
module ModuleInstanceMethods
#定义实例方法
end
end
method_add
class A
def self.method_added(name)
puts "#{name} is a new method"
end
end
class A
def a
end
end
a is a new method
此方法接受一个参数为新定义方法的方法名,若定义了此方法,以后每次为这个类增加一个新方法时都会调用method_add方法,类似的当定义了singleton_method_added方法时为对象添加单例方法时会被调用,对于类对象来说单例方法就是类方法。
Class#inherited
如果为给定的类定义了inherited方法,那么在为它生成子类时,inherited会被调用,唯一的调用参数是新的子类的名字:
class C
def self.inherited(subclass)
puts "#{self} just got subclassed by #{subclass}"
end
end
class D < C
end
D继承C,触发了inherited方法,输出结果:
C just got subclassed by D
Module#const_missing
在给定的模块或类中引用一个不可识别的常量时,该方法被调用:
class C
def self.const_missing(const)
puts "#{const} is undefined-setting it to 1."
const_set(const, 1)
end
end
puts C::A
puts C::A
输出结果:
A is undefined-setting it to 1.
1
1
附:rails activerecord回调方法(以创建新记录为例,更新记录也类似将下列create改为update即可):
save
valid?
(1) before_validation
(2) before_validation_on_create
validate
validate_on_create
(3) after_validation
(4) after_validation_on_create
(5) before_save
(6) before_create
数据库插入
(7) after_create
(8) after_save
共8个回调方法为上述标号(1)至(8)
分享到:
相关推荐
内容包括模型的基础操作、深入探讨模型查询、模型关联关系、模型校验以及回调函数的使用。 第五章“Rails中的控制器”,关注的是MVC架构中的控制器层。通过控制器层,开发者可以处理用户的输入,并将请求传递给模型...
- **调用回调**:说明如何触发回调函数。 - **跳过回调**:介绍如何在特定情况下跳过某个回调。 - **停止执行**:讲解如何在某个回调中阻止后续回调的执行。 - **关联回调**:解释如何在关联操作中触发回调。 - **...
6. 学习Rails的高级特性,如回调、观察者、缓存、异步处理等。 7. 熟悉测试,通过"Ruby On Rails[1].pdf"学习测试驱动开发。 8. 阅读"ruby on rails 学习资料pdf",巩固和扩展知识。 9. 实战项目,将所学应用于实际...
3. **元编程**:Ruby允许在运行时修改和创建类及方法,提供了强大的元编程能力,这对于Rails框架的许多特性至关重要,如ActiveRecord的动态属性和回调。 4. **块和迭代器**:Ruby中的块类似于其他语言的匿名函数,...
5. **回调**: 在模型的生命周期中可以定义各种回调函数,例如在保存之前或之后执行某些操作。 6. **自定义方法**: 可以在模型类中定义自定义的方法,实现特定的业务逻辑。 #### 五、高级用法 1. **分页**: 使用...
开发者可以通过定义回调函数来处理这些消息,例如回复文本、图片、音频等类型的消息。 4. **发送自定义响应**: 当接收到用户的请求后,开发者可以通过调用中间件提供的方法,构建并发送自定义的响应。这包括文本...
块(block)和 Proc 对象是Ruby的独特之处,它们可以用来实现迭代和回调功能。 Ruby的元编程能力非常强大,可以动态修改类和对象的行为。反射API(Reflection API)允许在运行时检查和操作对象、类和模块的内部结构...
利用`slack-ruby-client`的事件订阅功能,你可以定义回调函数来处理这些事件。 7. **创建Slack通知**: `slack-notifier` gem则用于发送简单的通知到Slack频道。你可以根据需要配置通知,包括消息文本、频道、以及...
Ruby的块(block)、 Proc 和 Lambda 是实现回调和高阶函数的关键。 元编程是Ruby的一大特色,它允许你在运行时修改代码。Ruby提供了许多工具来进行元编程,如`eval`函数可以执行字符串中的代码,`class_eval`和`...
块是Ruby中的一段可传递的代码,常用于迭代和回调,而闭包则允许函数保存外部作用域的状态。元编程能力让Ruby具备了在运行时修改自身的能力,这在构建灵活的框架时非常有用。 接下来,我们进入Rails的世界。Rails的...
}`,这在编写回调函数和事件处理时非常方便。 三、Ruby on Rails框架 Ruby的流行很大程度上归功于Ruby on Rails(简称Rails)这个Web开发框架。Rails遵循"约定优于配置"的原则,提供了丰富的内置功能和工具,使...
在函数式编程方面,Ruby支持块(blocks)和Proc对象,它们可以捕获代码块并在需要时执行,这在处理迭代和回调函数时非常有用。Lambda表达式提供了一种更严格的块定义方式,类似于函数,这在编写函数式风格的代码时...
- 闭包:块可以捕获其定义时的作用域内的变量,形成闭包,这使得Ruby的回调函数和函数式编程特性得以实现。 4. **模块**: - 模块用来组织代码,提供命名空间,也可以作为混入机制,实现代码复用。 - include...
8. 钩子(Hooks)和回调(Callbacks):Ruby允许在特定事件发生之前或之后执行代码,这些预定义的钩子或回调函数在很多场合都非常有用。 9. 模块扩展(Module#extend):使用extend可以将模块中的实例方法变成类...
Ruby的块(blocks)和 Proc 对象是其独特之处,它们提供了简洁的回调函数和迭代器。书中会深入解释这些概念,并通过实例展示它们在实际编程中的应用。Ruby还支持闭包,这是一种强大的工具,可以捕获和存储当前环境的...
此外,`data-*`属性用于传递额外的信息,如HTTP方法(GET或POST)和回调函数。 **jQuery与Rails的结合** 在Rails早期版本中,经常使用jQuery库来增强Ajax功能。jQuery简化了DOM操作和事件处理,并提供了`$.ajax()`...
通过《Beginning Rails 4》,读者不仅可以掌握 Ruby 和 Rails 的基础知识,还能深入了解 Web 开发的核心概念和技术。无论是新手还是有一定编程经验的开发者,都能从本书中学到实用的知识和技能,从而能够构建出高...
书中还将详细介绍Ruby的块(block)、Proc 和 Lambda,这些都是Ruby实现回调和闭包的关键工具。通过它们,你可以编写出更简洁、更具表达力的代码。此外,Ruby的迭代器和集合操作,如map、reduce、select等,提供了...