调用FactoryBot.create时会触发after_update回调吗?
为什么FactoryBot.create会触发after_update回调?
这种情况其实不是FactoryBot的默认行为——正常情况下,FactoryBot.create(:object)只会触发与创建相关的回调(比如before_create、after_create),不会触发after_update。你遇到的问题,大概率是你的代码(Factory定义或模型逻辑)里有额外操作,导致记录在创建完成后又被更新了。
下面是几种常见的原因和排查方向:
1. Factory定义中包含了更新操作
检查你的Factory代码,看看有没有使用after(:create)或类似钩子,在创建完成后修改并保存对象:
FactoryBot.define do factory :object do # ... 属性定义 after(:create) do |obj| obj.update(some_attribute: "updated_value") # 这里会触发after_update end end end
如果有这类逻辑,create执行完后会立即执行update,自然会触发after_update回调。
2. 模型的创建回调里隐含了更新
查看你的模型代码,有没有在before_create、after_create或before_save这类回调中,调用了save、update、touch或其他会修改并保存记录的方法:
class Object < ApplicationRecord after_create :sync_external_data private def sync_external_data self.update!(synced_at: Time.current) # 这里的update!会触发after_update end end
这种场景下,创建记录时会自动执行sync_external_data,进而触发更新回调。
3. 关联属性的处理触发了更新
如果你的模型有关联关系,且关联的回调会反向更新主模型,也可能导致这种情况。比如:
class Object < ApplicationRecord has_many :items, after_add: :update_item_count private def update_item_count(item) self.update!(item_count: items.count) # 更新主模型属性,触发after_update end end
如果你的Factory在创建object时同时创建了关联的items,那么after_add回调会触发主模型的更新,进而触发after_update。
排查小技巧
如果你不确定哪里触发了更新,可以在after_update回调里添加调试代码,追踪调用栈:
class Object < ApplicationRecord after_update do puts "after_update triggered by:" puts caller.join("\n") end end
运行FactoryBot.create后,查看控制台输出的调用栈,就能找到触发更新的具体代码位置了。
内容的提问来源于stack exchange,提问作者Francesco Mari
相关产品推荐
相关产品推荐

