调用FactoryBot.create时是否运行after_update?

时间:2018-05-24 16:41:00

标签: ruby-on-rails rails-activerecord factory-bot

在我的测试中,我看到在调用after_update后调用了FactoryBot.create(:object)。这是正常的吗?据我所知,只有在记录更新时才应该调用它,不是吗?

2 个答案:

答案 0 :(得分:0)

我可以看到有人将此报告为错误,并提供了很好的解释here

如果您的工厂正在添加关联(这是现阶段的假设 - 如果您可以在问题中添加更多内容,那就更好了),请从此处获取基本要素,代码运行如下:

示例工厂

FactoryGirl.create(
  :user,
  :account => FactoryGirl.create(:account)
)

如何调用:

account = Account.new
account.save! # Since this is Ruby, it'll evaluate this line as part of the hash first, before creating the user

user = User.new
user.account = account
user.save! # The hash has been evaluated and we're assigning the account created from the hash

因此,如果您有关联,则会创建account,在这种情况下,会在保存关联时更新。

要设置工厂以解决此问题,您可以使用以下内容:

factory :user do
  factory :user_with_account do
    after_create do |user|
      FactoryGirl.create(:account, :user => user)
    end
  end
end

factory :account do
  user
end

这对您的设置有何影响?有一个镜头,看看它是否提供了解决方案 - 让我知道你如何继续:)

答案 1 :(得分:0)

只有在更新对象时才会调用

after_update,但是如果您的工厂有关联或after_create操作,这些操作通常会导致模型更新,导致after_update成为class Client < ApplicationRecord after_create :ping after_update :pong def ping logger.info("---> after_create HOOK CALLED") end def pong logger.info("---> after_update HOOK CALLED") end end 触发。

使用ActiveRecord 5的一个例子:

c = Client.create!(name: "test")
#   (0.4ms)  BEGIN
#   Client Create (1.4ms)  INSERT INTO "clients" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["name", "test"], ["created_at", "2018-05-24 17:06:24.076085"], ["updated_at", "2018-05-24 17:06:24.076085"]]
# --->  after_create HOOK CALLED
#   (4.0ms)  COMMIT

c.update! name: "test2"
#   (0.8ms)  BEGIN
#   Client Update (2.3ms)  UPDATE "clients" SET "name" = $1, "updated_at" = $2 WHERE "clients"."id" = $3  [["name", "test2"], ["updated_at", "2018-05-24 17:06:36.525448"], ["id", "a3d49153-2f25-48c3-8319-61c2fb6ea173"]]
# ---> after_update HOOK CALLED
#    (0.9ms)  COMMIT
]

创建和更新对象按预期运行:

FactoryBot.create(:client)
#    (1.2ms)  BEGIN
#   Client Create (0.9ms)  INSERT INTO "clients" ("name", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["name", "Montana tigers"], ["created_at", "2018-05-24 17:11:57.138995"], ["updated_at", "2018-05-24 17:11:57.138995"]]
# ---> after_create HOOK CALLED
#    (1.1ms)  COMMIT

FactoryBot的行为相同:

 SqlBulkCopy bulkCopy = new SqlBulkCopy(Connection);

 foreach (DataColumn column in dt.Columns)
 {
     bulkCopy.ColumnMappings.Add(column.ColumnName, column.ColumnName);
 }

 bulkCopy.DestinationTableName = "nsi." + classifierData.Info.TableName;
 bulkCopy.WriteToServer(dt);