这一篇讲了你的Active Record objects的整个生命过程。
在rails中,objects可以created,updated,destroyed。rails允许你before或者after上述操作时候进行逻辑操作。
这章主要讲的就是在对于model的各种操作的before或者after时可以采用的操作。对于所有的操作,总体来说有两种方式:
一、注册一个函数在回调函数处,这里填上函数的名字,然后再定义这个函数。这里要声明的是,最好这个函数定义为protected的或者private的,目的是为了封装,避免这个接口暴露。大体形式如下(这种形式主要是在我们的回调函数比较复杂的时候使用)
classUser < ActiveRecord::Base
validates:login,:email, presence: true
before_validation:ensure_login_has_a_value #before_validation是一个回调函数的名称
protected
defensure_login_has_a_value
iflogin.nil?
self.login = email unlessemail.blank?
end
end
end
二、直接用一个proc块放在后面,这种形式主要适用于我们后面仅有一两句代码的简单形式
classUser < ActiveRecord::Base
validates:login,:email, presence: true
before_createdo|user|
user.name = user.login.capitalize ifuser.name.blank?
end
end
下面我们说说可以使用的回调函数(注意,下面每个小块中出现的回调函数次序都是在该情况下回调函数被调用的次序)
1.Creating an Object(比如,创建一个object时,最先调用before_validation最后调用after_save)
-
before_validation #validation验证前
-
after_validation #validation验证后
-
before_save #存储前
-
around_save #存储时
-
before_create #创建前
-
around_create #创建时
-
after_create #创建后
-
after_save #存储后
-
before_validation
-
after_validation
-
before_save
-
around_save
-
before_update
-
around_update
-
after_update
-
after_save
3. Destroying an Object
-
before_destroy
-
around_destroy
-
after_destroy
after_initialize这个回调函数将在object实例化后调用,也就是执行new或者从数据库加载model时。你可以用它代替直接重写initialize函数
after_find这个回调函数在从数据库加载modle时调用(其实就是find什么的),当同时定义了after_initialize函数,after_find将在after_initialize之前调用,通过下面的例子可以看出来
classUser < ActiveRecord::Base
after_initializedo|user|
puts"You have initialized an object!"
end
after_finddo|user|
puts"You have found an object!"
end
end
>> User.new
You have initialized an object!
=>#<User id: nil>
>> User.first
You have found an object!
You have initialized an object!
=>#<User id: 1>
下面我们再说说哪些函数会跳过这些callbacks(通过名字大概可以看出每个函数是什么意思,后面还会讲)
-
decrement
-
decrement_counter
-
delete
-
delete_all
-
increment
-
increment_counter
-
toggle
-
touch
-
update_column
-
update_columns
-
update_all
-
update_counters
最后,我们可以选择性的选择是否执行callback
其实就是配合使用if或者unless,只有if或者unless成立时才会执行。其实就是一个参数
例子如下
classOrder < ActiveRecord::Base
before_save:normalize_card_number,if::paid_with_card?
end
if是key,指向一个object。
可以是symbol(符号),就像上面的,要求后面是一个函数的名字
可以是字符串,要求是可执行的rails代码
classOrder < ActiveRecord::Base
before_save:normalize_card_number,if:"paid_with_card?"
end
可以是proc块,要求返回true或false
classOrder < ActiveRecord::Base
before_save:normalize_card_number,
if:Proc.new{ |order| order.paid_with_card? }
end
还有一点,事务处理callback
有两个额外的callback,after_commit
和 after_rollback,这两个函数和after_save相似,但也不同,他们在数据库commit或者rollback才会调用的。这一点在你的系统要和其他系统共同处理的时候。最简单的例子就是当我们设计一个文件管理系统时,我们的数据库记录着我们有那些文件路径,而这些文件在磁盘中存着。我们删除一条数据库记录时或者增加一条数据库记录时可能会有文件与存储的不一致问题,这个用这类回调函数最合适了。
对了,忘了一点,我们所有的callback都可以使用on这个参数约定它作用的函数,on指向一个数组,里面存着函数名。
下面是个例子
classPictureFile < ActiveRecord::Base
after_commit:delete_picture_file_from_disk,:on=> [:destroy]#在destroy函数调用
defdelete_picture_file_from_disk
ifFile.exist?(filepath)
File.delete(filepath)
end
end
end
假如你不加上on,那么每个action都会调用这个回调函数的