首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >`before_create`和`after_create`之间有什么区别,什么时候使用哪一个?

`before_create`和`after_create`之间有什么区别,什么时候使用哪一个?
EN

Stack Overflow用户
提问于 2014-04-09 12:14:32
回答 3查看 13.9K关注 0票数 13

我知道before_create是在对象转换到数据库之前调用的,而after_create是在之后调用的。

只有当对象无法满足数据库常量(唯一键等)时,才会调用before_create和after_create。另外,我可以将来自after_create的所有逻辑都放在before_create中

我是不是遗漏了什么?

EN

回答 3

Stack Overflow用户

发布于 2014-04-09 13:06:43

为了理解这两个回调,首先你需要知道这两个回调是什么时候被调用的。下面是ActiveRecord回调的顺序:

(-)保存

(-)有效

(1) before_validation

(-)验证

(2) after_validation

(3) before_save

(4) before_create

(-)创建

(5) after_create

(6) after_save

(7) after_commit

您可以看到,before_create是在after_validation之后调用的,在简单的上下文中,这个回调是在您的ActiveRecord满足验证之后调用的。此before_create通常用于在验证后设置一些额外的属性。

现在转到after_create,您可以看到这是在将记录持久存储到DB之后创建的。人们通常使用它来做一些事情,比如发送通知,记录日志。

对于这个问题,你应该什么时候使用它?答案是‘你根本不应该使用它’。ActiveRecord回调是反模式的,经验丰富的Rails开发人员将其视为代码气味,您可以通过使用服务对象包装来实现所有这些。这里有一个简单的例子:

代码语言:javascript
运行
复制
class Car < ActiveRecord::Base
  before_create :set_mileage_to_zero
  after_create  :send_quality_report_to_qa_team
end

can be rewritten in

# app/services/car_creation.rb

class CarCreation

  attr_reader :car

  def initialize(params = {})
    @car = Car.new(params)
    @car.mileage = 0
  end

  def create_car
    if car.save
      send_report_to_qa_team
    end 
  end

  private

  def send_report_to_qa_team
  end
end

如果你有一个简单的应用程序,那么回调是可以的,但随着你的应用程序的增长,你将会挠头,不确定是什么设置了这个或那个属性,测试将非常困难。

再想一想,我仍然认为你应该广泛使用回调,体验一下重构它的痛苦,然后你就会学会避免它;)祝你好运

票数 19
EN

Stack Overflow用户

发布于 2014-04-09 12:49:55

在将对象保存到数据库之前,可以使用before_create回调设置对象的属性。例如,为记录生成唯一标识符。将其放入after_create中将需要另一个数据库调用。

票数 5
EN

Stack Overflow用户

发布于 2014-04-09 13:37:39

before_create:

在db中保存新对象之前将被调用。当此方法返回false时,它将通过回滚来阻止创建。

因此,当你需要做一些事情,比如在保存之前检查一些东西,这在验证中是不合适的,你可以在before_create中使用它们。

例如:在创建新的Worker之前,需要向Master请求权限。

代码语言:javascript
运行
复制
before_create :notify_master

def notify_master
  # notify_master via ipc and 
  # if response is true then return true and create this successfully
  # else return false and rollback
end

另一个用途是,正如Trung Lê建议的那样,您希望在保存之前格式化一些属性,如大写名称等。

after_create:

第一次将object保存到数据库后调用。当你不想中断创建,只记下创建的笔记或在创建后触发某些东西时,这是很有用的。

例如:在使用角色mod创建新的user之后,我们想要通知其他mods

after_create :notify_mod,:is_mod?

代码语言:javascript
运行
复制
def notify_mod
  # send notification to all other mods
end

编辑:以下评论的

问:将notify_mod放在after_create中而不是before_create中有什么好处

答:有时在数据库中保存对象时,由于数据库端验证或其他问题,它可能会回滚。

现在,如果你在创建之前已经编写了notify_mod,那么即使创建没有完成,它也会被处理。毫无疑问,它会回滚,但它会产生开销。所以这很耗时

如果您已将其放在after_create中,则只有在成功创建记录后,notify_mod才会执行。从而减少了发生回滚时的开销。

另一个原因是,通知必须在用户创建之后而不是之前发送,这是合乎逻辑的。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22952664

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档