gpt4 book ai didi

ruby-on-rails - 升级到 Rails 5 时,序列化为哈希的现有数据会产生错误

转载 作者:行者123 更新时间:2023-12-04 03:46:40 25 4
gpt4 key购买 nike

我目前正在将 Ruby on Rails 应用程序从 4.2 升级到 5.0,并且在将数据存储为序列化哈希的字段方面遇到了障碍。例如,我有

class Club
serialize :social_media, Hash
end

创建新俱乐部并输入社交媒体时,一切正常,但对于现有的社交媒体数据,我得到:

ActiveRecord::SerializationTypeMismatch: Attribute was supposed to be a Hash, but was a ActionController::Parameters.



如何转换 ActionController::Parameter 中的所有现有数据对简单哈希的对象?数据库是mysql。

最佳答案

来自 fine manual :

serialize(attr_name, class_name_or_coder = Object)

[...] If class_name is specified, the serialized object must be of that class on assignment and retrieval. Otherwise SerializationTypeMismatch will be raised.



所以当你这样说的时候:
serialize :social_media, Hash

ActiveRecord 将需要未序列化的 social_media成为 Hash .但是,正如 vnbrs 所述, ActionController::Parameters不再是 Hash 的子类像以前一样,你有一个满是序列化的表 ActionController::Parameters实例。如果您查看 social_media 中的原始 YAML 数据列,您会看到一堆字符串,例如:
--- !ruby/object:ActionController::Parameters...

而不是像这样的哈希:
---\n:key: value...

您应该修复所有现有数据以在 social_media 中使用 YAML 化哈希。而不是 ActionController::Parameters以及那里的其他任何东西。这个过程会有些不愉快:
  • 拉每个social_media从表中作为字符串。
  • 将该 YAML 字符串解压缩为 Ruby 对象:obj = YAML.load(str) .
  • 将该对象转换为哈希:h = obj.to_unsafe_h .
  • 将该哈希写回 YAML 字符串:str = h.to_yaml .
  • 将该字符串放回数据库中以替换 中的旧字符串(1) .

  • 注意 to_unsafe_h 来电 (3) .只需调用 to_h (或 to_hash 就此而言)在 ActionController::Parameters 上在 Rails5 中实例会给你一个异常(exception),你必须包含一个 permit首先调用过滤参数:
    h = params.to_h                   # Exception!
    h = params.permit(:whatever).to_h # Indifferent access hash with one entry

    如果您使用 to_unsafe_h (或 to_unsafe_hash )然后你会在 HashWithIndifferentAccess 中得到全部内容.当然,如果你真的想要一个普通的旧哈希,那么你会说:
    h = obj.to_unsafe_h.to_h

    也可以打开无关紧要的访问包装器。这也假设您只有 ActionController::Parameterssocial_media所以您可能需要包含 obj.respond_to?(:to_unsafe_hash)检查你如何打开你的 social_media值(value)观。

    您可以通过 Rails 迁移中的直接数据库访问来完成上述数据迁移。这可能真的很麻烦,具体取决于低级 MySQL 接口(interface)的好坏。或者,您可以在迁移中创建一个简化的模型类,如下所示:
    class YourMigration < ...
    class ModelHack < ApplicationRecord
    self.table_name = 'clubs'
    serialize :social_media
    end

    def up
    ModelHack.all.each do |m|
    # Update this to match your real data and what you want `h` to be.
    h = m.social_media.to_unsafe_h.to_h
    m.social_media = h
    m.save!
    end
    end

    def down
    raise ActiveRecord::IrreversibleMigration
    end
    end

    您想使用 find_in_batchesin_batches_of而是 all如果你有很多 Club当然。

    如果您的 MySQL 支持 json列和 ActiveRecord 与 MySQL 的 json 一起使用列(抱歉,这里是 PostgreSQL 人),那么这可能是将列更改为 json 的好时机并远离 serialize .

    关于ruby-on-rails - 升级到 Rails 5 时,序列化为哈希的现有数据会产生错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48773769/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com