Rails 4中store_方法作用是什么?升级到Rails 6后如何复现其功能?
store_xxx!方法作用与Rails 6兼容方案 方法作用说明
你遇到的store_document!不属于Rails原生核心语法糖,主要来自两种常见的技术场景:
- 第三方附件管理Gem自动生成(概率最高):Rails 4.2时期主流的附件管理Gem Paperclip、CarrierWave都会自动生成该类回调方法。以Paperclip为例,当你在模型中声明
has_attached_file :document时,Gem会自动注册before_save类型的store_document!回调,作用是将上传的附件写入指定存储位置(本地/云存储),同时把附件的文件名、大小、格式等元数据同步写入模型对应数据库字段。 - ActiveRecord Store序列化配置生成:如果你在模型中使用过Rails原生
store宏(比如store :extra, accessors: [:document], coder: JSON),Rails 4.2版本会自动生成store_<属性名>!方法,作用是把内存中修改的序列化属性值强制序列化写入对应的数据库text列。
Rails 5之后两种场景的底层逻辑都发生了变化:Paperclip停止维护不再兼容高版本Rails,官方推出内置的Active Storage作为附件管理方案;同时Rails原生Store的store_xxx!逻辑被合并到属性脏追踪的默认更新流程中,不再单独暴露公共方法,所以升级到Rails 6后会抛出方法不存在的错误。
Rails 6复现功能方案
根据你的实际业务场景选择对应方案即可:
场景1:原逻辑为附件管理
- 推荐方案:迁移到Rails内置Active Storage
- 执行
rails active_storage:install生成系统附件表,运行数据库迁移 - 把模型中原附件声明替换为
has_one_attached :document - 原有
skip_callback代码可以直接删除,需要保留skip_processing?跳过逻辑的话,新增如下代码即可:
before_save do self.document = nil if skip_processing? end - 执行
- 兼容方案:如果要保留原有Paperclip逻辑,可以切换到社区维护的Rails 6兼容fork版本
kt-paperclip,配置完成后原有store_document!回调会自动恢复。
场景2:原逻辑为序列化属性存储
Rails 5+已经把store_xxx!的逻辑合并到默认的属性更新流程中,正常修改属性后调用save/update会自动完成序列化写入,直接移除原有skip_callback代码即可。如果一定要保留和旧版完全一致的方法,可以手动在模型中定义:
def store_document! # 把下方的extra替换为你实际存储序列化数据的数据库列名 self.extra = self.class.serialized_attributes['extra'].serialize(extra) save_changes end
内容的提问来源于stack exchange,提问作者Dave
相关产品推荐
相关产品推荐

