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

Eug*_*eMi 7 ruby-on-rails ruby-on-rails-3 rails-activerecord

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

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

我错过了什么吗?

Tru*_* Lê 11

为了理解这两个回调,首先你需要知道何时调用这两个回调.以下是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
Run Code Online (Sandbox Code Playgroud)

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

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


Luk*_*uke 5

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


Har*_*dik 5

之前_创建:

将在 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
Run Code Online (Sandbox Code Playgroud)

另一种用途是Trung Lê建议您在保存之前格式化某些属性,例如大写名称等。

后创建:

第一次在数据库中保存对象后调用。就在您不想中断创建而只想记下创建或在创建后触发某些内容时,这很有用。

例如:在创建新user角色后,mod我们要通知其他模组

after_create :notify_mod, :is_mod?

def notify_mod
  # send notification to all other mods
end
Run Code Online (Sandbox Code Playgroud)

编辑:对于下面的评论

问:用notify_modinafter_create代替 有before_create什么好处?

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

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

如果您已将其放入,after_createnotify_mod只有在成功创建记录后才会执行。因此,如果发生回滚,则减少开销。

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