为自定义类设置 yaml_column_permissed_classes 的正确方法

pat*_*vey 4 ruby-on-rails rails-activerecord ruby-on-rails-6.1

由于此安全建议,序列化属性需要使用 YAML.safe_load 和允许类的安全列表。

我遇到的问题是我想使用自定义类 (Foo::Bar) 并且至少在 Rails 6.1 中您需要在application.rb.

    config.active_record.yaml_column_permitted_classes = [
      Symbol,
      String,
      Foo::Bar
    ]
Run Code Online (Sandbox Code Playgroud)

问题是,在内部运行它(按原样)application.rb会出现以下错误:

 uninitialized constant AppName::Application::Foo (NameError)
Run Code Online (Sandbox Code Playgroud)

如果我添加到 require 语句的顶部application.rb,那么应用程序可以正常启动,但是,在开发中我会收到警告(因为类及其常量被重新定义)

 uninitialized constant AppName::Application::Foo (NameError)
Run Code Online (Sandbox Code Playgroud)

我发现的唯一干净的方法是根本不使用配置,你只需设置 Rails真正想要设置的内容,这就是 ->

 warning: previous definition of SomeConstant was here
Run Code Online (Sandbox Code Playgroud)

这不会产生任何错误,但是,感觉就像我超出了 Rails 希望我做的事情。

是否有正确的方法来初始化自定义类application.rb

phi*_*hil 5

在 Rails 7 上,我发现将东西放入初始化程序中(我使用config/initializers/active_record.rb并使用Rails.application.config.after_initializehook.

你最终会得到这样的结果:

# config/initializers/active_record.rb
# this has to be here because we need MyClass, which isn't loaded early enough to do in environments/production.rb

Rails.application.config.after_initialize do
  ActiveRecord.yaml_column_permitted_classes += [
    Date,
    BigDecimal,
    ActiveSupport::TimeWithZone,
    Time,
    ActiveSupport::TimeZone,
    ActiveSupport::HashWithIndifferentAccess,
    MyClass
  ]
end
Run Code Online (Sandbox Code Playgroud)

老实说,您还可以这样做config/application.rb

    config.after_initialize do
      ActiveRecord.yaml_column_permitted_classes += [
        Date,
        BigDecimal,
        ActiveSupport::TimeWithZone,
        Time,
        ActiveSupport::TimeZone,
        ActiveSupport::HashWithIndifferentAccess,
        MyClass
      ]
    end
Run Code Online (Sandbox Code Playgroud)