为什么我在 rails 5 的 Rails 控制台中收到严重的参数错误? [英] Why am I getting strong parameter errors in the Rails Console in rails 5?

查看:53
本文介绍了为什么我在 rails 5 的 Rails 控制台中收到严重的参数错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在我的控制台中调用它(ap 是很棒的打印宝石):

I want to call this in my console (ap is the awesome print gem):

ap Purchase.last(10)

但我收到此错误:

ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash

它是这样工作的:

irb(main):020:0> ap Purchase.last
#<Purchase:0x00007f86b792a320> {
                              :id => 28445,
                         :user_id => 10177,
                      :product_id => nil,
                    :product_type => nil,
                           :price => 9.0,
                    :gateway_code => nil,
                     :gateway_msg => nil,
                :gateway_response => nil,
                      :created_at => Fri, 18 May 2018 22:20:10 UTC +00:00,
                      :updated_at => Fri, 18 May 2018 22:20:10 UTC +00:00,
                  :checkout_total => 9.0,
                      :successful => true,
                         :cart_id => 17242,
                   :report_errors => nil,
    :transacted_value_of_products => 9.0,
            :comp_credits_applied => 0.0
}

没有 ap 像这样:

irb(main):022:0> Purchase.last(10)
D, [2018-05-25T20:58:54.692575 #70552] DEBUG -- :   Purchase Load (0.5ms)  SELECT  "purchases".* FROM "purchases" ORDER BY "purchases"."id" DESC LIMIT $1  [["LIMIT", 10]]
+-------+---------+------------+-------------+-------+-------------+-------------+-------------+-------------+--------------+-------------+------------+---------+-------------+-------------+-------------+
| id    | user_id | product_id | product_... | price | gateway_... | gateway_msg | gateway_... | created_at  | updated_at   | checkout... | successful | cart_id | report_e... | transact... | comp_cre... |
+-------+---------+------------+-------------+-------+-------------+-------------+-------------+-------------+--------------+-------------+------------+---------+-------------+-------------+-------------+
| 28436 | 10471   |            |             | 5.0   |             | Completed   | {"mc_gro... | 2018-05-... | 2018-05-1... | 5.0         | true       | 17228   | {}          | 5.0         | 0.0         |
| 28437 | 9754    |            |             | 1.99  |             | Completed   | {"mc_gro... | 2018-05-... | 2018-05-1... | 2.48        | true       | 15273   | {}          | 1.99        | 0.0         |
| 28438 | 10472   |            |             | 9.0   |             |             | {\n  "id... | 2018-05-... | 2018-05-1... | 9.0         | true       | 17231   | {}          | 9.0         | 0.0         |
| 28439 | 10348   |            |             | 9.0   |             |             |             | 2018-05-... | 2018-05-1... | 9.0         | true       | 17235   |             | 9.0         | 0.0         |

但不带参数和 ap

irb(main):021:0> ap Purchase.last(3)
ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
    from (irb):21

事实证明我无能为力:

irb(main):023:0> ap Purchase.find(28444)
ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
    from (irb):23

irb(main):024:0> ap Purchase.find(28444).gateway_response
ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
    from (irb):24

怎么回事?

推荐答案

发生了什么以及为什么

ActionController::Parameters(这是params 在控制器中使用的)用于继承自 HashWithIndifferentAccess 的继承自 Hash.所以 ActionController::Parameters <Hash 曾经是真的,就像这样:

What's Happening and Why

ActionController::Parameters (which is what params works with in controllers) used to inherit from HashWithIndifferentAccess which inherits from Hash. So ActionController::Parameters < Hash used to be true as would something like:

params.require(:x).permit(some_hash: %i[key1 key2]).is_a? Hash

如果你从 params 中挖掘出一个 Hash:

If you were digging a Hash out of params:

some_hash = params.require(:x).permit(some_hash: ...)

并在模型中对其进行序列化:

and serializing that in a model:

class M < ApplicationRecord # Or ActiveRecord::Base in the past
  serialize :h, Hash
end
#...
m.h = some_hash

你可能会在你的数据库中得到一些像这样的 YAML:

you could end up with some YAML like this in your database:

--- !ruby/object:ActionController::Parameters
...

而不是预期的纯 YAMLized 哈希.

rather than the expected plain YAMLized hash.

但是 Rails5 出现了,ActionController::Parameters 不再从 Hash 继承:

But then Rails5 comes along and ActionController::Parameters no longer inherits from Hash:

  • 使 ActionController::Parameters 不再继承自 HashWithIndifferentAccess.
  • Make ActionController::Parameters no longer inherits from HashWithIndifferentAccess.

并在 ActionController::Parameters 上调用 to_hto_hash 现在会引发异常.

and calling to_h or to_hash on an ActionController::Parameters now raises an exception.

如果您升级代码并尝试加载包含序列化数据的模型:

If you upgrade your code and try to load a model with serialized data in it:

serialize :h, Hash

然后模型将从 h 加载文本,解析 YAML 以获取 ActionController::Parameters 实例,并调用 to_h on以确保它有一个哈希值,然后你会得到一个异常.

then the model will load the text from h, parse the YAML to get an ActionController::Parameters instance, and call to_h on it to make sure it has a Hash, and you get an exception.

您需要做几件事:

  1. 修复您的控制器以确保它们从 params 中获得真正的哈希值.
  2. 修复您的数据,使您拥有序列化的哈希值,而不是 ActionController::Parameters 实例.
  1. Fix your controllers to make sure they get real hashes out of params.
  2. Fix your data so that you have serialized hashes rather than ActionController::Parameters instances.

修复控制器是一个简单的事情,只需在尚未真正散列的参数上调用 to_unsafe_h.

Fixing the controllers is a simple matter of calling to_unsafe_h on the parameters that aren't yet real hashes.

修复数据更丑陋.我可能会使用低级数据库接口(即任何地方都没有 ActiveRecord)浏览表,从每一行中读取 YAML,YAML.load 它,通过调用 将其转换为哈希>to_unsafe_h,然后写回 the_real_hash.to_yaml 文本.您可以在 WHERE 子句中使用 like '--- !ruby/object:ActionController::Parameters%' 过滤器来仅处理损坏的行.

Fixing the data is uglier. I'd probably go through the tables using the low level database interface (i.e. no ActiveRecord anywhere), read the YAML out from each row, YAML.load it, convert it to a hash by calling to_unsafe_h on it, and then writing back the_real_hash.to_yaml text. You could use a like '--- !ruby/object:ActionController::Parameters%' filter in the WHERE clause to only deal with the broken rows.

我还强烈建议您在那里时停止使用 serialize.serialize 有点麻烦,在数据库中没有使用 YAML 的明智方法;现在也几乎不需要它了,因为 PostgreSQL 和 MySQL 都有原生的 JSON 支持(但我不确定 ActiveRecord 对 MySQL 的 JSON 的支持有多好).

I'd also strongly recommend that you stop using serialize while you're there. serialize is a bit of a kludge and there's no sane way to work with YAML inside the database; there's also little need for it now that both PostgreSQL and MySQL have native JSON support (but I'm not sure how well ActiveRecord supports MySQL's JSON).

这篇关于为什么我在 rails 5 的 Rails 控制台中收到严重的参数错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆