Ruby3.1.2+Rails6.1.7调用discard gem报Psych错误求助
修复Ruby 3.1.2 + Rails 6.1.7中调用discard#discard时的Psych::DisallowedClass异常
可能原因
- Rails 6.1.7在Ruby 3.1环境下,YAML序列化/反序列化的权限配置存在局部覆盖问题,discard gem处理记录时触发了未授权类的反序列化,全局配置未覆盖该场景。
- discard gem内部操作可能绕过ActiveRecord的YAML配置,直接调用了Psych底层方法。
解决方案尝试
1. 确保配置正确生效(取消注释并重启应用)
你之前的配置处于注释状态,先取消注释并重启应用(即使无Spring也需重启服务器):
# config/application.rb config.active_record.yaml_column_permitted_classes = [Symbol, Hash, Array, ActiveSupport::HashWithIndifferentAccess, ActiveSupport::TimeWithZone, Time] config.active_record.use_yaml_unsafe_load = false # 优先保持安全,非必要不开启unsafe模式 config.active_support.use_yaml_unsafe_load = false
额外添加ActiveSupport的YAML允许类配置(针对非ActiveRecord列的序列化场景):
config.active_support.permitted_yaml_classes = [ActiveSupport::TimeWithZone, Time, Symbol, Hash, Array, ActiveSupport::HashWithIndifferentAccess]
2. 针对discard操作的局部兼容处理
若全局配置不生效,可在调用discard的代码块中临时授权类:
# 临时添加允许类,操作后恢复 original_permitted = Psych::ClassLoader::PermittedClasses.dup Psych::ClassLoader::PermittedClasses.add(ActiveSupport::TimeWithZone) object.discard Psych::ClassLoader::PermittedClasses.replace(original_permitted)
或使用unsafe模式临时包裹(仅建议在可信场景下使用):
Psych.unsafe_load do object.discard end
3. 升级discard gem到最新版本
检查discard gem是否有Ruby 3.1/Rails 6.1.7的兼容修复,执行更新命令:
bundle update discard
4. 初始化脚本补全配置(针对缓存序列化场景)
若discard依赖缓存机制触发异常,添加初始化脚本覆盖缓存的YAML解析逻辑:
# config/initializers/psych_permit_classes.rb Rails.application.config.after_initialize do ActiveSupport::Cache::Store.send(:define_method, :load) do |data| if data.is_a?(String) && data.start_with?("---") YAML.load(data, permitted_classes: [ActiveSupport::TimeWithZone, Time, Symbol, Hash, Array, ActiveSupport::HashWithIndifferentAccess]) else super(data) end end end
验证步骤
每次修改配置或代码后,重启应用并测试object.discard操作,确认异常是否消失。
内容的提问来源于stack exchange,提问作者Nikita Fedyashev
相关产品推荐
相关产品推荐

