Rails API Serializer更新对象时含if语句返回旧数据的原因咨询
Rails API Serializer更新后返回旧数据的原因分析
问题场景
更新Store关联的Schedule数据时,代码包含if @store.schedule_relations.present?判断时,接口返回旧数据;移除该if语句后,无需手动reload就能返回更新后的正确数据。希望明确该现象的底层原因。
相关代码
更新逻辑代码:
if @store.schedule_relations.present? params[:schedule_params].each do |schedule_param| @store.btc_box_merchant_lku_schedule_relations.find_by(day: schedule_param[:day]).update_attributes!(is_open: schedule_param[:is_open], opening_time: schedule_param[:opening_time], closing_time: schedule_param[:closing_time]) end end
Store模型定义:
has_many :schedules
Schedule模型定义:
belongs_to :store
原因解析
核心原因是Rails的关联缓存机制:
- 执行
@store.schedule_relations.present?时,Rails会立即查询数据库获取关联的Schedule记录,并将结果缓存到@store对象的内存中。 - 后续通过
find_by更新数据库中的Schedule记录时,只会修改数据库数据,不会同步更新@store内存中已缓存的旧关联数据。 - 当Serializer序列化
@store时,会优先使用内存缓存里的旧数据,而非重新查询数据库,因此返回旧值。
移除if语句后,没有提前触发关联查询缓存,Serializer在处理关联数据时才会去数据库拉取最新记录,所以能返回正确的更新后数据。
另外注意到模型定义的关联是has_many :schedules,但代码中使用的是schedule_relations和btc_box_merchant_lku_schedule_relations,如果是关联别名,需确认has_many的class_name、foreign_key配置是否正确,但这不是缓存问题的直接诱因。
补充说明
- 解决该问题除了调用
@store.reload清空整个对象缓存,还可以用@store.schedules.reset(若关联名称为schedules)单独重置关联缓存,让Serializer下次查询时获取最新数据。 - 避免在更新关联数据前提前触发关联查询,也能避免缓存旧数据的问题。
内容的提问来源于stack exchange,提问作者kevser
相关产品推荐
相关产品推荐

