Callback详解
Callbacks
Callback Registration
在 Rails 中,回调(Callbacks)是一种在模型目标的生命周期中履行特定代码的机制。回调能够在模型目标的创立、更新、删去等操作中履行特定的代码,例如保存目标前履行某些逻辑,或许在目标被删去前履行整理操作。
Rails 中的回调分为两种类型:前置回调(before callbacks)和后置回调(after callbacks)。前置回调在操作履行之前履行,后置回调在操作履行之后履行。能够运用 before_
和 after_
前缀来指定回调的类型。
以下是一些常见的回调类型:
before_validation
和after_validation
:在验证目标之前和之后履行回调。before_save
和after_save
:在保存目标之前和之后履行回调。before_create
和after_create
:在创立目标之前和之后履行回调。before_update
和after_update
:在更新目标之前和之后履行回调。before_destroy
和after_destroy
:在删去目标之前和之后履行回调。
要注册回调,能够在模型类中运用 before_
或 after_
前缀来指定回调的类型,然后指定要履行的办法:
class User < ApplicationRecord
before_save :normalize_email
private
def normalize_email
self.email = email.downcase
end
end
在上面的比如中,咱们将 normalize_email
办法注册为 before_save
回调。这意味着在保存 User
目标之前,Rails 将主动调用 normalize_email
办法。在 normalize_email
办法中,咱们将 email 特点转换为小写字母,以保证一切邮件地址都是小写的。
需求留意的是,注册回调时有必要指定要履行的办法的称号,能够是一个实例办法或一个类办法。回调办法中能够运用模型目标的任何特点或办法来履行特定的逻辑,例如更新其他目标、发送电子邮件等。
运用回调能够让咱们更灵敏地操控模型目标的行为,能够在目标的生命周期中履行恣意的操作。一起,回调也能够进步代码的可读性和可维护性,使代码更易于了解和修正。
Available Callbacks
在 Rails 中,能够注册多种类型的回调来在模型目标的生命周期中履行特定代码。以下是可用的回调类型:
创立和保存目标
before_validation
:在验证目标之前履行回调。after_validation
:在验证目标之后履行回调。before_save
:在保存目标之前履行回调,包含新建和更新操作。around_save
:在保存目标之前和之后履行回调,运用yield
办法来履行保存操作。after_save
:在保存目标之后履行回调,包含新建和更新操作。before_create
:在创立目标之前履行回调。around_create
:在创立目标之前和之后履行回调,运用yield
办法来履行创立操作。after_create
:在创立目标之后履行回调。
更新和删去目标
before_update
:在更新目标之前履行回调。around_update
:在更新目标之前和之后履行回调,运用yield
办法来履行更新操作。after_update
:在更新目标之后履行回调。before_destroy
:在删去目标之前履行回调。around_destroy
:在删去目标之前和之后履行回调,运用yield
办法来履行删去操作。after_destroy
:在删去目标之后履行回调。
相关目标
before_add_association
:在增加相关目标之前履行回调。after_add_association
:在增加相关目标之后履行回调。before_remove_association
:在删去相关目标之前履行回调。after_remove_association
:在删去相关目标之后履行回调。
其他
after_initialize
:在实例化目标之后履行回调。after_find
:在从数据库中查找目标之后履行回调。
要注册回调,能够在模型类中运用相应的回调办法来指定回调的类型,然后指定要履行的办法。例如,要在保存目标之前履行特定的逻辑,能够运用 before_save
办法:
class User < ApplicationRecord
before_save :normalize_email
private
def normalize_email
self.email = email.downcase
end
end
在上面的比如中,咱们将 normalize_email
办法注册为 before_save
回调。这意味着在保存 User
目标之前,Rails 将主动调用 normalize_email
办法。在 normalize_email
办法中,咱们将 email 特点转换为小写字母,以保证一切邮件地址都是小写的。
需求留意的是,回调办法中能够运用模型目标的任何特点或办法来履行特定的逻辑,例如更新其他目标、发送电子邮件等。运用回调能够让咱们更灵敏地操控模型目标的行为,能够在目标的生命周期中履行恣意的操作。一起,回调也能够进步代码的可读性和可维护性,使代码更易于了解和修正。
回调前更新特点会怎么办
假如在回调中测验更新特点,或许会导致一些问题。由于回调的履行次序是不确定的,所以在某些状况下,特点的更新或许会被其他回调掩盖或被数据库中的耐久化数据掩盖。
例如,假如咱们在 before_save
回调中测验更新某个特点,而在 after_save
回调中有另一个回调也测验更新同一个特点,那么终究特点值或许会是不确定的,由于最终履行的回调会掩盖之前的值。
为了防止这种状况,应该尽量防止在回调中更新特点。假如的确需求更新特点,能够运用 update_column
办法来更新特点,该办法能够直接将特点更新到数据库中,而不触发其他回调。可是需求留意,运用 update_column
办法将越过一切的验证,包含模型界说的验证,因而需求慎重运用。
别的,假如在回调中需求运用其他模型目标的数据,能够将逻辑移动到操控器或服务目标中,以保证数据正确性和可维护性。
after_initialize and after_find
after_initialize
和 after_find
都是 ActiveRecord 模型中的回调办法。
after_initialize
办法会在创立新的 ActiveRecord 目标或从数据库中加载现有目标时被调用。该办法能够用来履行恣意初始化逻辑,例如设置默认值或初始化相关目标。与其他回调不同,after_initialize
办法不需求接纳任何参数,由于它是在目标创立之后当即调用的。
以下是一个示例,演示怎么运用 after_initialize
办法在创立新目标时设置默认值:
class User < ApplicationRecord
after_initialize :set_defaults
private
def set_defaults
self.status ||= "active"
end
end
在上面的比如中,咱们将 set_defaults
办法注册为 after_initialize
回调。在 set_defaults
办法中,咱们检查 status
特点是否为 nil
,假如是,则将其设置为默认值 "active"
。
after_find
办法会在从数据库中查找 ActiveRecord 目标之后被调用。该办法能够用来履行恣意的后处理逻辑,例如核算特点或更新相关目标。after_find
办法接纳一个参数,即从数据库中加载的 ActiveRecord 目标。
以下是一个示例,演示怎么运用 after_find
办法核算用户的年纪:
class User < ApplicationRecord
after_find :calculate_age
private
def calculate_age
self.age = Date.today.year - birthday.year
end
end
在上面的比如中,咱们将 calculate_age
办法注册为 after_find
回调。在 calculate_age
办法中,咱们运用从数据库中加载的用户目标的生日特点核算用户的年纪,并将成果保存到年纪特点中。
需求留意的是,after_find
办法只会在从数据库中加载目标时被调用,而不会在实例化新目标时被调用。假如需求在目标创立后履行某些逻辑,应该运用 after_initialize
办法。
after_touch什么 意思
after_touch
是Rails中的一个回调办法,它会在一个已相关的目标被touch操作更新后被触发。在Rails中,touch操作指的是在更新一个目标时,一起更新相关目标的更新时刻戳(updated_at
)字段。这个操作能够用来完成缓存失效、从头核算统计数据等功能。
例如,假定你有一个User
模型和一个Post
模型,一个用户能够具有多篇文章。当你更新某篇文章时,你或许需求更新相关用户的更新时刻戳,以便在用户列表或其他地方正确地排序。你能够运用touch
选项来完成这一点,如下所示:
class Post < ApplicationRecord
belongs_to :user, touch: true
end
class User < ApplicationRecord
has_many :posts
after_touch :update_sorting
def update_sorting
# 更新用户排序,例如更新`updated_at`字段
self.touch
end
end
这段代码界说了两个Active Record模型,Post
和User
,它们之间存在一个一对多的相相关系。
在Post
模型中,运用belongs_to :user, touch: true
声明晰一个归于相关,表明一篇文章归于一个用户。touch: true
选项表明当文章被更新时,主动更新与之相关的用户的updated_at
字段,以便在用户列表或其他地方正确地排序。
在User
模型中,运用has_many :posts
声明晰一个具有多个相关,表明一个用户能够具有多篇文章。after_touch :update_sorting
声明晰一个after_touch
回调办法,表明当与之相关的一篇文章被touch操作更新时,主动调用update_sorting
办法更新用户排序,例如更新updated_at
字段。
在update_sorting
办法中,运用self.touch
办法更新用户的updated_at
字段,以便在用户列表或其他地方正确地排序。
需求留意的是,这段代码中运用了touch操作来完成主动更新相关目标的更新时刻戳,这能够用来完成缓存失效、从头核算统计数据等功能。在Rails中,touch操作是一种常见的技巧,能够用来简化代码并进步性能。
需求留意的是,after_touch
回调办法只会在touch操作触发更新时被调用。假如你手动更新了updated_at
字段,after_touch
回调办法不会被调用。
运转回调
这些是Rails中常用的Active Record模型操作办法,下面别离介绍它们的效果:
-
create(attributes = {})
:创立一个新的模型目标并将其保存到数据库中。能够传入一个哈希表参数attributes
表明要创立的模型目标的特点值。 -
create!(attributes = {})
:与create
相同,但假如保存失利会抛出反常。 -
destroy
:从数据库中删去当时模型目标。 -
destroy!
:与destroy
相同,但假如删去失利会抛出反常。 -
destroy_all
:删去契合条件的一切模型目标,不进行任何回谐和验证。 -
destroy_by(conditions)
:依据条件删去契合条件的单个模型目标,不进行任何回谐和验证。 -
save
:将当时模型目标的特点值保存到数据库中。假如目标不存在,则创立一个新的目标。 -
save!
:与save
相同,但假如保存失利会抛出反常。 -
save(validate: false)
:与save
相同,但不进行模型目标的验证。 -
toggle!
:将当时模型目标的布尔类型特点取反并保存到数据库中。 -
touch
:更新当时模型目标的updated_at
字段,并保存到数据库中。这个办法一般用于更新缓存或触发回调办法。 -
update_attribute(name, value)
:更新当时模型目标的单个特点值,并直接保存到数据库中,不进行任何验证。 -
update(attributes)
:更新当时模型目标的特点值,并保存到数据库中。能够传入一个哈希表参数attributes
表明要更新的特点值。 -
update!(attributes)
:与update
相同,但假如更新失利会抛出反常。 -
valid?
:检查当时模型目标是否经过验证。假如验证失利,能够运用errors
办法检查错误信息。
这些办法是Rails中常用的Active Record模型操作办法,能够用于创立、更新、删去和验证模型目标。需求留意的是,这些办法中有些会触发回调办法、进行验证或抛出反常,详细运用时需求依据实际状况挑选适宜的办法。