在更新操作中调用 ActiveRecord .reload 方法导致规范对象具有 nil id

Posted

技术标签:

【中文标题】在更新操作中调用 ActiveRecord .reload 方法导致规范对象具有 nil id【英文标题】:Calling ActiveRecord .reload method in update action causing spec object to have nil id 【发布时间】:2019-01-01 15:12:19 【问题描述】:

问题已解决

添加.reload 后,为了防止dog_vaccination_records 使用不同的数据两次保存到数据库中,我的一些规范失败并出现相同的错误:

Failure/Error: Unable to find matching line from backtrace
     ActiveRecord::RecordNotFound:
       Couldn't find DogVaccinationRecord without an ID
     # ./app/controllers/dog_vaccination_record_controller.rb:9:in `update'

在失败的规范中设置断点并调用 dog_medical_recordsdog_vaccination_records 确实返回具有 nil id 的两个对象,但否则信息正确:

#<DogVaccinationRecord:0x007fed0bf322d0
id: nil,
dog_record_id: 6,
archived_at: nil,
created_at: nil,
updated_at: nil>

.reload 是什么导致测试数据库中对象的 id 为nil?如果我在创建时调用 .reloadnil ID 会有意义,但为什么更新时该对象尚未在数据库中?

我做了一些谷歌搜索,想知道这个错误是否与 .reload 仅重新加载“控制台环境中的最新代码”而不是“重新初始化现有对象”有关 this explanation of .reload .

TL:DR:帮助我了解.reload 方法的工作原理,这应该让我更好地了解.reload 如何影响我的规格。

通过FactoryGirl初始化规范中的dog_medical_record:

dog_vaccination_record = FactoryGirl.build(:dog_vaccination_record_base, dog_medical_record: dog.dog_medical_record)

DogMedicalRecords 控制器更新操作:

def update
  @dog_vaccination_records = @dog.dog_record.dog_vaccination_records.decorate
  if @dog_medical_records.update_attributes(params[:dog_medical_records])
    @dog_vaccination_records.reload.update_attributes(params[:dog_vaccination_records]) if params[:dog_vaccination_records]

    @dog_medical_records.errors.add(:dog_vaccination_records, "fields are not valid") unless @dog_vaccination_records.valid?
    initialize_resource
  end

respond_with @dog_medical_records
end

编辑 07/26/2018

问题是我使用 .build 来构建 FactoryBot 对象,而我应该使用 .create.build 就像在没有.save 的情况下调用.new,而使用.create 创建对象并将其保存到数据库中。

【问题讨论】:

您的@dog_vaccination_records 并没有保存在数据库中(根据您向我们展示的内容)。所以无法重新加载。 另外,你不会混淆来自 rails 控制台的 reload! 和来自 ActiveRecord 的 reload 吗? 对不起@SergioTulentsev,我不得不稍微重构一下这段代码来保护项目。我已将所有提及.reload! 的内容都修复为仅.reload,因为它在控制器的更新操作中。是的,我把它和 ActiveRecord 方法混淆了。 @SergioTulentsev,我正要问你,@dog_vaccination_records 一开始没有被保存是什么意思。但后来我将 FactoryGirl.build() 更改为 FactoryGirl.create 并出现了 ID。这就是你说的,不是吗? .build.create的区别? 正是如此,是的。 【参考方案1】:

已解决

问题是我使用 .build 来构建 FactoryBot 对象,而我应该使用 .create。 .build 就像在没有 .save 的情况下调用 .new,而使用 .create 创建对象并将其保存到数据库 source。

【讨论】:

以上是关于在更新操作中调用 ActiveRecord .reload 方法导致规范对象具有 nil id的主要内容,如果未能解决你的问题,请参考以下文章

Ajax 调用未从 ActiveRecord 返回最新数据

是否有更惯用的方法来更新 ActiveRecord 属性哈希值?

Castle ActiveRecord + NHibernate 中的交易傻瓜

有没有办法选择一个 ActiveRecord 关系进行更新?

是否在 HABTM 关系中的联接表中调用 ActiveRecord 回调?

长时间任务后,ActiveRecord 在简单更新期间抛出 Mysql2::Error::ConnectionError