`
ddl1st
  • 浏览: 95844 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

ruby和rails中的回调函数

阅读更多
文章转载自 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)
分享到:
评论

相关推荐

    Ruby On Rails中文教材(PDF)

    Ruby On Rails中文教材(PDF)

    Ruby on Rails中文指南

    Ruby on Rails中文指南

    Ruby on Rails Tutorial

    在这个全球互联的世界中,计算机编程和 Web 应用程序开发都在迅猛发展,我很期待能为中国的开发者提供 Ruby on Rails 培训。学习英语这门世界语言是很重要的,但先通过母语学习往往会更有效果。正因为这样,当看到 ...

    Ruby on Rails Guides v2 - Ruby on Rails 4.2.5

    Ruby on Rails Guides v2 - Ruby on Rails 4.2.5

    《Ruby on Rails Web开发学习实录》

    在目前的主流web开发技术中,基于ruby语言的rails框架是做网站开发速度最快的工具。它可以达到j2ee框架开发速度的5~10倍,并且代码量也非常少。另外由于代码量的大幅度减少,整个网站维护的工作量也大大降低。 ...

    ruby on rails社区网站开发源码

    ruby on rails社区网站开发源码

    免费Ubuntu系统ruby on rails安装【保姆级教程】

    Ubuntu系统ruby on rails安装 Ubuntu系统ruby on rails安装 Ubuntu系统ruby on rails安装 Ubuntu系统ruby on rails安装 Ubuntu系统ruby on rails安装 Ubuntu系统ruby on rails安装 Ubuntu系统ruby on rails安装 ...

    Ruby for Rails

    第一部分讲述Ruby和Rails的编程环境。第二部分和第三部分与 Rails紧密联系,着重对Ruby这门语言进行详细介绍;所采用的Rails应用示例,既说明了Ruby的特性,也给出了有关Rails的重要信息。第四部分讲述了如何应用第...

    ruby on rails对mongodb的操作

    ruby on rails对mongodb的操作ruby on rails对mongodb的操作ruby on rails对mongodb的操作ruby on rails对mongodb的操作

    ruby on rails 开发环境包(ruby1.8.7,rails2.2.3)

    ruby on rails 开发环境包(ruby1.8.7,rails2.2.3)

    Ruby on rails tutorial中文版(第二版)

    除了讲到 Ruby on Rails 之外,涉及到的技术还有 HTML、CSS、数据库、版本控制、测试和部署。为了达成学习目标,本书使用了一个完整的方案:通过实例学习使用 Rails 从零开始创建一个真正的程序。如 Derek Sivers 在...

    提升Ruby on Rails性能的几个解决方案

    Ruby On Rails 框架自它提出之日起就受到广泛关注,在“不要重复自己”,“约定优于配置”等思想的指导下,Rails 带给 Web 开发者的是极高的开发效率。 ActiveRecord 的灵活让你再也不用配置繁琐的 Hibernate 即可...

    Ruby On Rails教程

    Ruby On Rails 官方教程,这本书讲解如何使用 Ruby on Rails 框架开发应用,以及如何把应用部署到生成环境。...这本书是《Ruby on Rails Tutorial, Third Edition》的简体中文版,由作者授权翻译和销售。

    ruby on rails最佳敏捷开发

    最新Ruby on Rails中文版介绍,欢迎大家共同学习此最新的技术!随着Ruby和Rails版本的不断升级,这些知识也在不断的更新,谢谢的支持!

    ruby on rails api

    ruby on rails api方便查阅

    ruby on rails 教程源码

    ruby on rails 教程源码,配合原书使用

    [Michael Hartl] Ruby on Rails Tutorial

    “The author is clearly an expert at the Ruby language and the Rails framework, but more than that, he is a working software engineer who introduces best practices throughout the text.” —Greg ...

    ruby on rails最新版

    ruby on rails最新版 这是本人精心收集的重要软件

Global site tag (gtag.js) - Google Analytics