序列化后,值在数据库中更新为 ActiveSupport::HashWithIndifferentAccess

value is updated in DB with ActiveSupport::HashWithIndifferentAccess after serializing

我正在尝试将列值更新为数据库中的散列。数据库中的列是文本。

在我的模型中,

serialize :order_info

在控制器中我有更新操作

  def update
    Order.update_order_details(update_params, params[:order_info])
    head :no_content
  end

我没有为 order_info 做强参数,因为 order_info 是一个任意散列,经过研究,强参数不支持任意散列

我要传递的值如下所示

"order_info": {
    "orders": [
        {
            "test": "AAAA"
        }
    ], 
"detail": "BBBB",
"type": "CCCC"
}

但是当我尝试更新值时,它会在数据库中得到更新,例如

--- !ruby/object:ActionController::Parameters parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess   comments:   - !ruby/hash:ActiveSupport::HashWithIndifferentAccess     test: AAAA   detail: BBBB   type: CCCC permitted: false 

serialize 是 ActiveSupport::HashWithIndifferentAccess 的一个实例,所以我猜这就是它在值中的原因。我怎样才能摆脱多余的东西并只更新散列?

如果您想在不进行任何过滤的情况下从 params[:order_info] 中解包所有 ActionController::Parameters 内容,那么最简单的方法就是调用 to_unsafe_h(或其别名 to_unsafe_hash) :

hash = params[:order_info].to_unsafe_h

在 Rails4 中应该会在 hash 中给你一个普通的旧 Hash 但 AFAIK Rails5 会给你一个 ActiveSupport::HashWithIndifferentAccess 所以你可能想添加一个 to_h 调用:

hash = params[:order_info].to_unsafe_h.to_h

to_h 调用在 Rails4 中不会执行任何操作,但在升级到 Rails5 时会让您少担心一件事情。

然后你的更新调用:

Order.update_order_details(
  update_params,
  params[:order_info].to_unsafe_h.to_h # <-------- Extra DWIM method calls added
)

应该会在数据库中为您提供您要查找的 YAML:

"---\n:order_info:\n  :orders:\n  - :test: AAAA\n  :detail: BBBB\n  :type: CCCC\n"

您可能还想加入一个 deep_stringify_keys 调用:

params[:order_info].to_unsafe_h.to_h.deep_stringify_keys

取决于您想要在 YAMLizied 哈希中使用哪种键。