欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ActiveRecord验证和回调4 博客分类: railsruby ActiveRecordafter_save 

程序员文章站 2024-03-19 21:01:04
...

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