为什么我在 rails 5 的 Rails 控制台中收到严重的参数错误? [英] Why am I getting strong parameter errors in the Rails Console in rails 5?
问题描述
我想在我的控制台中调用它(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 fromHashWithIndifferentAccess
.
并在 ActionController::Parameters
上调用 to_h
或 to_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.
您需要做几件事:
- 修复您的控制器以确保它们从
params
中获得真正的哈希值. - 修复您的数据,使您拥有序列化的哈希值,而不是
ActionController::Parameters
实例.
- Fix your controllers to make sure they get real hashes out of
params
. - 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屋!