`before_create`和`after_create`之间有什么区别?何时使用哪个?

时间:2014-04-09 04:14:32

标签: ruby-on-rails ruby-on-rails-3 rails-activerecord

我知道在将对象转换为数据库之前调用before_create,之后调用after_create。

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

我错过了什么吗?

3 个答案:

答案 0 :(得分:9)

为了理解这两个回调,首先你需要知道何时调用这两个回调。以下是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开发人员认为它代码嗅觉,你可以通过使用Service对象来实现所有这一切。这是一个简单的例子:

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

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

第二个想法,我仍然认为你应该广泛使用回调并经历重构它的痛苦然后你会学会避免它;)goodluck

答案 1 :(得分:4)

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

答案 2 :(得分:3)

<强> before_create:

在db中保存新对象之前将调用

。当此方法返回false时,将通过回滚来阻止创建。

因此,如果您需要在保存之前检查某些内容(在验证中不合适),您可以在before_create中使用它们。

例如:在创建新Worker之前请求Master获取权限。

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:

第一次在数据库中保存对象后调用。就在你不想中断创作而只是记下创作或在创作后触发某些东西时,这很有用。

例如:创建角色为user的新mod后,我们要通知其他mod

after_create:notify_mod,:is_mod?

def notify_mod
  # send notification to all other mods
end

编辑:以下评论

问:将notify_mod放入after_create代替before_create的优势是什么?

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

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

如果您已将其放在after_create中,那么notify_mod只会在成功创建记录时执行。因此,如果发生回滚,则减少开销。

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