当前位置:首页 > 开发 > 编程语言 > 编程 > 正文

ActiveRecord验证和回调4

发表于: 2012-07-17   作者:chen_miao   来源:转载   浏览次数:
摘要: 9 回调概述回调是在对象生命周期中某一时刻调用的方法。在Active Record对象从数据库中创建、保存、更新、删除、验证和装载的时候就可以编写回调代码。9.1 注册回调使用回调有个规则就是要注册它们。就像平常使用方法一样,使用一个macro-style类方法来注册。class User < ActiveRecord::Basevalidates_presence_of :login, :

9 回调概述
回调是在对象生命周期中某一时刻调用的方法。在Active Record对象从数据库中创建、保存、更新、删除、验证和装载的时候就可以编写回调代码。

9.1 注册回调
使用回调有个规则就是要注册它们。就像平常使用方法一样,使用一个macro-style类方法来注册。
class User < ActiveRecord::Base
validates_presence_of :login, :email
before_validation :ensure_login_has_a_value

protected
def ensure_login_has_a_value
    if login.nil?
      self.login = email unless email.black?
    end
end
end
macro-style类方法也接受一个block,如果代码很短就可以考虑把它写在block中。
class User < ActiveRecord::Base
validates_presence_of :login, :email
before_create { |user| user.name = user.login.capitalize if user. name.blank ?}
end

声明回调方法是保护和私有,这是很有用的做法。如果是公共的,就能从外部其他模型中调用该方法。

10 验证回调

10.1 创建对象
* before_validation
* before_validation_on_create
* after_validation
* after_validation_on_create
* before_save
* before_create
* INSERT OPERATION
* after_create
* after_save

10.2 更新对象
* before_validation
* before_validation_on_update
* after_validation
* after_validation_on_update
* before_save
* before_update
* UPDATE OPERATION
* after_update
* after_save

10.3 删除对象
* before_destroy
* DELETE OPERATION
* after_destroy

10.4 after_initialize和after_find
使用new方法或者从数据库中载入记录就可以使用after_initialize。

当从数据库中载入记录时就可以使用after_find,如果两种方法都定义了,after_find是在after_initialize之前调用。
这两个回调方法和其它的有一点点不同,它们没有before_*的版本。而且注册他们唯一的方法就是定义方法。如果使用macro-style来注册的话,会被忽略掉。
class User < ActiveRecord::Base
def after_initialize
    puts "You have initialized an object!"
end
def after_find
    puts "You have found an object!"
end
end

>> User.new
You have initialize an object!
=> #<User id: nil>

>>User.first
You have found an object!
You have initialized an object!
=>#<User id: 1>

12 跳过回调
在验证时有些方法可以跳过回调,请小心使用这些方法。
* decrement
* decrement_counter
* delete
* delete_all
* find_by_sql
* increment
* increment_counter
* toggle
* update_all
* update_counters

13 终止执行
在模型中注册回调,它们按队列执行。这些队列将包含在模型的验证中,注册回调,数据库执行操作。
整个回调被封装起来,如果有回调方法执行并返回false或者抛出一个异常,回调就终止。

14 关系回调
回调可以通过模型关系工作,并且能够被它们定义。

class User < ActiveRecord::Base
has_many :posts, :dependent => :destroy
end

class Post < ActiveRecord::Base
after_destroy :log_destroy_action
def log_destroy_action
    puts 'Post destroyed'
end
end

>> user = User.first
=> #<User id:1>
>> user.posts.create!
=> #<Post id: 1, user_id: 1>
>> user.destroy
Post destroyed
=> #<User id: 1>

15 有条件的回调
和验证类似,回调也可以附加条件。使用:if和:unless选项,该选项可以使用符号、字符串和Proc对象作为参数。

15.1 使用符号的:if和:unless
使用的符号参数一般是指向一个方法,如果这个方法返回false,那么回调就不执行。
class Order < ActiveRecord::Base
before_save :normalize_card_number, :if => :paid_with_card?
end

15.2 使用字符串的:if和:unless
字符串参数是可能通过eval执行的Ruby代码。当描述一个很短的条件时可以用它。
class Order < ActiveRecord::Base
before_save :normalize_card_number, :if => "paid_with_card?"
end

15.3 使用Proc对象的:if和:unless
通过条件在一行时,使用这个参数是再好不过的了。
class Order < ActiveRecord::Base
before_save :normalize_card_number,
    :if => Prod.new{|order| order.paid_with_card?}
end

15.4 多条件的回调
当用条件来限制回调时,可以把:if和:unless同时写上。
class Comment < ActiveRecord::Base
after_create :send_email_to_author, :if => :author_wants_emails?,
    :unless => Proc.new{ |comment| comment.post.ingnore_comment?}
end

16 回调类
虽然多数情况下,使用内建的回调方就足够了。ActiveRecord也让你可以自己定义类来创建回调方法,而且这个过程很容易。
class PictureFileCallbacks
def after_destroy(picture_file)
    File.delete(picture_file.filepath) if File.exists?(picture_file.filepath)
end
end

当在类中声明一个回调方法,会用模型对象作为参数。可以这样来使用:
class PictureFile < ActiveRecord::Base
after_destroy PictureFileCallbacks.new
end
我们声了一个回调的实例方法,这样就要实例化一个PictureFileCallbacks对象。很多时候会用类方法:
class PictureFileCallbacks
def self.after_destroy(picture_file)
    File.delete(picture_file.filepath) if File.exists?(picture_file.filepath)
end
end

如果回调方法是这样定义的,就不用实例化了。
class PictureFile < ActiveRecord::Base
after_destroy PictureFileCallbacks
end

17 观察者
观察者和回调类似,但又有很大的不同。回调会意图污染没有直接关系的模型,而观察者允许你在模型的外部添加同样的功能。例如:有一个User模型,没有包含发送验证邮件的代码,应当考虑使用观察者。

17.1 创建观察者
例如,User模型要为每个新创建的用户发送email。因为发送email和我们的模型没有直接的联系,所以就创建观察者来包含这些功能。
class UserObserver < ActiveRecord::Observer
def after_create(model)
    # code to send confirmation email...
end
end

和回调类一样,观察者方法接受观察者模型作为参数。

17.2 注册观察者
观察者一惯是放在app/models目录和在config/enviroment.rb中注册。上面例子UserObserver应保存在app/models/user_observer.rb文件中和在config/environment.rb中加上:
config.active_record.observers = :user_observer

17.3 共享观察者
观察者可以添加到更多的模型中:
class MailerObserver < ActiveRecord::Observer
observe :registration, :user
def after_create(model)
    # code to send cofirmation email...
end
end

这个例子中,每当一个Registration或者User创建的时候,就会调用after_create方法。要注意的就是新的MailerObserver观察者要注册到config/environment.rb中。
config.active_record.observers = :mailer_observer

 

form:http://hi.baidu.com/haifreeidea/blog/item/6b6bfdef6f96aef3b0fb9566.html

ActiveRecord验证和回调4

  • 0

    开心

    开心

  • 0

    板砖

    板砖

  • 0

    感动

    感动

  • 0

    有用

    有用

  • 0

    疑问

    疑问

  • 0

    难过

    难过

  • 0

    无聊

    无聊

  • 0

    震惊

    震惊

编辑推荐
软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用
彻底把回调的各种的使用都弄明白了,呵呵,记录一下。当然下面的回调是最粗浅的使用方式,昨天看了
java接口回调是指:可以把使用某一接口的类创建的对象的引用赋给该接口声明的接口变量,那么该接口
在上一篇随笔中,搭建了一个寄宿于控制台项目的wcf服务和客户端.今天晚上时间比较充裕,看了下wcf的消
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel&g
回调这种思想大家应该都用过,只是很多人不知道那是回调的一种罢了,前几天整理了一下自己对于回调
  有点类似模板的功能,可以使用函数指针作为参数,当调用函数时,使用void *进行传递参数,细致
1. 什么是回调函数 回调函数(callback Function),顾名思义,用于回调的函数。 回调函数只是一个
WebForm中回发或回调参数无效问题的解决 解决 .NET中回发或回调参数无效问题的解 该错误的详细提示
使用委托实现同步回调与异步回调 使用委托实现同步回调与异步回调 使用委托可以执行的一项有用操作
版权所有 IT知识库 CopyRight © 2009-2015 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号