RSpec测试中更新Record属性为{}未生效的问题排查求助
问题:如何正确设置Record的attribute属性为{}并在查询中匹配?
我需要将Record类型记录record的attribute属性设置为{},尝试了以下操作但遇到问题:
已尝试的操作
- spec文件中:
record.update_attribute(attribute: {}) record.attribute = {} - FactoryBot文件中:
trait :update_attr do attribute {{}} end
遇到的问题
- 测试调用的脚本中,使用
Record.where(attribute: {})无法找到目标记录,推测是该属性存在默认值 - spec文件内打印记录时,
attribute显示为{},但脚本中查询返回的记录该属性是已填充的默认值,并非{} - 已检查FactoryBot文件,未找到该属性的默认值设置
示例代码
spec文件
require 'rails_helper' require_relative Rails.root.join('script/test.rb') RSpec.describe FixRecord do let(:record) { FactoryBot.create(:record) } subject { described_class.call } describe 'class#call' do before do preset.configurations = {} end it 'fixes record' do # 此处打印会显示记录ID及attribute为{} puts 'record', preset.attribute, record.id subject expect(preset.attribute).to eq({foo:'bar'}) end end end
脚本文件
class ResetError < StandardError; end BATCH_SIZE = 1000 def self.call new.call end def call # 此处调用Record.find(x).attribute返回已填充的属性而非{} binding.pry Record.where("attribute=?", "{}") do |record| record.update(attribute: {foo: 'bar'}) end end
解决思路及方案
1. 定位默认值来源
FactoryBot中无默认值设置,需排查其他位置:
- 数据库层面:检查Record对应的数据库表,确认
attribute字段是否设置了JSON类型的默认值(如'{"key": "default_val"}') - 模型层面:查看Record模型代码,是否存在类似
attribute :attribute, default: -> { { default_key: 'default_val' } }的默认值定义
2. 正确设置空对象并持久化
要确保{}被真正写入数据库,避免被默认值覆盖:
# 方式1:直接更新数据库字段,跳过模型回调和验证 record.update_columns(attribute: {}) # 方式2:若需触发模型回调,先赋值再强制保存 record.attribute = {} record.save(validate: false) # 若有验证拦截,可临时跳过
在FactoryBot中,可通过after(:create)确保值被写入:
trait :update_attr do attribute { {} } after(:create) do |record| record.update_columns(attribute: {}) end end
3. 正确查询空JSON对象
不同数据库对空JSON的查询语法有差异,避免直接字符串匹配的兼容性问题:
PostgreSQL
# 推荐写法 Record.where(attribute: {}) # 或原生SQL写法 Record.where("attribute = '{}'::jsonb")
MySQL
Record.where("attribute = '{}'")
4. 验证数据库实际存储值
在脚本的binding.pry中,直接查询数据库确认字段真实值:
sql = "SELECT attribute FROM records WHERE id = #{record.id}" raw_value = ActiveRecord::Base.connection.execute(sql).first['attribute'] puts raw_value # 确认是否为真正的空JSON对象{}
内容的提问来源于stack exchange,提问作者mangocaptain
相关产品推荐
相关产品推荐

