After_update запускается при вызове FactoryBot.create? - PullRequest
0 голосов
/ 24 мая 2018

В моем тесте я вижу, что after_update вызывается после вызова FactoryBot.create(:object).Это нормально?Насколько я знаю, он должен вызываться только при обновлении записи, нет?

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

after_update вызывается только при обновлении объекта, однако, если у вашей фабрики есть ассоциации или after_create действия, это часто приводит к обновлению модели, вызывая срабатывание after_update.

Пример, использующий ActiveRecord 5:

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

Создание и обновление объекта ведут себя как ожидалось:

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 ведет себя так же:

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
0 голосов
/ 24 мая 2018

Я вижу, что кто-то сообщает об этом как об ошибке, с хорошим объяснением здесь .

Чтобы извлечь из этого самое необходимое, если ваша фабрика добавляет ассоциацию (это предположениена данном этапе - если бы вы могли добавить немного больше к вашему вопросу, это было бы здорово), код работает следующим образом:

Пример фабрики

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

Как это относится к вашей настройке?Сделайте попытку и посмотрите, дает ли это решение - дайте мне знать, как вы справляетесь:)

...