Psych在Rails版本更新后出现的错误。

huangapple go评论93阅读模式
英文:

Psych errors after Rails version update

问题

我们最近将一个客户的应用程序从Rails 4升级到Rails 5。然而,在运行测试套件后,尝试创建对象时出现了以下问题:

  1. 失败/错误:
  2. @ens_response = EnsResponse.create!(
  3. edi_request_body: @response.edi_request_body,
  4. edi_body: @response.edi_data,
  5. reject_reason: @response.attributes.try(:[], :reject_reason).try(:[], :text),
  6. response_attributes: @response.attributes
  7. )
  8. Psych::DisallowedClass:
  9. 尝试加载未指定的类:Policy

其中Policy是我们app/models/文件夹中的一个模型。

我们尝试更改YAML文件的加载方式如下:

  1. @service_hash ||= YAML.load_file(
  2. Rails.root.join('config', 'mcp_services.yml'),
  3. permitted_classes: [Policy],
  4. aliases: true
  5. )[Rails.env]

但没有成功。

我们还尝试更改application.rb文件,使用以下行:

  1. config.active_record.yaml_column_permitted_classes = [
  2. Symbol,
  3. ActiveSupport::HashWithIndifferentAccess,
  4. ActionController::Parameters

但只是收到以下错误:

  1. 失败/错误:require File.expand_path("../../config/environment", __FILE__)
  2. NoMethodError:
  3. 未定义方法 `yaml_column_permitted_classes=' for ActiveRecord::Base:Class

您有什么想法可能导致这个问题?本地的Psych版本为psych(默认:3.0.2),Rails版本为gem 'rails', '5.2.8'

提前感谢! Psych在Rails版本更新后出现的错误。

英文:

We recently updated a client's application from Rails 4 to rails 5.
However, after running the test suite the following issue appeared whilst trying to create an object:

  1. Failure/Error:
  2. @ens_response = EnsResponse.create!(
  3. edi_request_body: @response.edi_request_body,
  4. edi_body: @response.edi_data,
  5. reject_reason: @response.attributes.try(:[], :reject_reason).try(:[], :text),
  6. response_attributes: @response.attributes
  7. )
  8. Psych::DisallowedClass:
  9. Tried to load unspecified class: Policy

Where Policy is a model in our app/models/ folder.

We tried changing the loading of the YAML to the following:

  1. @service_hash ||= YAML.load_file(
  2. Rails.root.join('config', 'mcp_services.yml'),
  3. permitted_classes: [Policy ],
  4. aliases: true
  5. )[Rails.env]

But it was to no avail.

We also tried changing the application.rb file to use the following line:

  1. config.active_record.yaml_column_permitted_classes = [
  2. Symbol,
  3. ActiveSupport::HashWithIndifferentAccess,
  4. ActionController::Parameters

but just got the error:

  1. Failure/Error: require File.expand_path("../../config/environment", __FILE__)
  2. NoMethodError:
  3. undefined method `yaml_column_permitted_classes=' for ActiveRecord::Base:Class

Any idea what might be causing this issue?
Local psych is at version psych (default: 3.0.2) and rails is on gem 'rails', '5.2.8'

Thanks in advance! Psych在Rails版本更新后出现的错误。

答案1

得分: 1

将以下部分翻译为中文:

"Quick unsafe hack is to set this in application.rb..."

"More involved is to add an initializer in config/initializers. The initializer tells rails what classes to allow when loading yaml."

"config/initializers/yaml_loader.rb"

"Psych::ClassLoader::ALLOWED_PSYCH_CLASSES = [Policy,
ActionController::Parameters,
ActiveSupport::HashWithIndifferentAccess,
ActiveSupport::TimeWithZone,
ActiveSupport::TimeZone,
DateTime,
]"

"module Psych
class ClassLoader
ALLOWED_PSYCH_CLASSES = [] unless defined? ALLOWED_PSYCH_CLASSES
class Restricted < ClassLoader
def initialize classes, symbols
@classes = classes + Psych::ClassLoader::ALLOWED_PSYCH_CLASSES.map(&:to_s)
@symbols = symbols
super()
end
end
end
end"

英文:

Quick unsafe hack is to set this in application.rb...

  1. config.active_record.use_yaml_unsafe_load = true

More involved is to add an initializer in config/initializers. The initializer tells rails what classes to allow when loading yaml.

config/initializers/yaml_loader.rb

  1. Psych::ClassLoader::ALLOWED_PSYCH_CLASSES = [Policy,
  2. ActionController::Parameters,
  3. ActiveSupport::HashWithIndifferentAccess,
  4. ActiveSupport::TimeWithZone,
  5. ActiveSupport::TimeZone,
  6. DateTime,
  7. ]
  8. module Psych
  9. class ClassLoader
  10. ALLOWED_PSYCH_CLASSES = [] unless defined? ALLOWED_PSYCH_CLASSES
  11. class Restricted &lt; ClassLoader
  12. def initialize classes, symbols
  13. @classes = classes + Psych::ClassLoader::ALLOWED_PSYCH_CLASSES.map(&amp;:to_s)
  14. @symbols = symbols
  15. super()
  16. end
  17. end
  18. end
  19. end

答案2

得分: 0

  1. 经过更彻底的调查,发现错误是由于访问 `@response.attributes` 属性引起的,类似于这样:
  2. ```ruby
  3. @ens_response = EnsResponse.create!(response_attributes: @response.attributes)

这是因为前述属性是一个包含多个对象的哈希(Hash),其中包括一个名为 policy: 的属性,该属性是来自相同模型类(Policy)的对象,因此 Psych 尝试加载未指定的类引起了错误。

修复方法是将该属性强制转换为 JSON 字符串(因为这是所需的模式行值类型):

  1. @ens_response = EnsResponse.create!(
  2. edi_request_body: @response.edi_request_body,
  3. edi_body: @response.edi_data,
  4. reject_reason: @response.attributes.try(:[], :reject_reason).try(:[], :text),
  5. response_attributes: @response.attributes.to_json
  6. )

故事的教训:在序列化之前使用调试器,如 Pry,检查所有项的属性。

  1. <details>
  2. <summary>英文:</summary>
  3. After more thorough investigation, it turns out that the error is being caused by accessing the `@response.attributes` property, something similar to this:
  4. ```ruby
  5. @ens_response = EnsResponse.create!(response_attributes: @response.attributes)

It was due the fact that the aforementioned property is Hash, that contains several objects, including a property called policy: that is an object from the same model class (Policy), hence Psych trying to load an unspecified class caused an error.

The fix was to force-convert this property to a JSON string (since that's the schema row value type required):

  1. @ens_response = EnsResponse.create!(
  2. edi_request_body: @response.edi_request_body,
  3. edi_body: @response.edi_data,
  4. reject_reason: @response.attributes.try(:[], :reject_reason).try(:[], :text),
  5. response_attributes: @response.attributes.to_json
  6. )

Moral of the story: Use debuggers such as Pry and check the properties of all items before serialization.

huangapple
  • 本文由 发表于 2023年3月31日 23:00:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/75899997.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定