为什么我在rails 5的Rails控制台中遇到强大的参数错误?

时间:2018-05-26 01:00:34

标签: ruby-on-rails rails-activerecord strong-parameters awesomeprint

我想在我的控制台中调用它(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

事实证明我无能为力:

import pyqrcode
from qrtools import qrtools
from PIL import Image
import zbar
qr = pyqrcode.create("She got two litle horns and they get me a litle bit")
qr.png("horn.png", scale=6)
qr = qrtools.QR()
scanner = zbar.Scanner()
qr.decode("horn.png")
print(qr.data)

发生了什么事?

1 个答案:

答案 0 :(得分:3)

发生了什么以及为什么

ActionController::Parameters(这是params在控制器中的工作原理)用于继承自HashWithIndifferentAccess继承的Hash。所以ActionController::Parameters < Hash曾经如此:

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

如果您正在挖掘Hash中的params

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

并在模型中序列化:

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

你最终可能会在你的数据库中找到像这样的YAML:

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

而不是预期的普通YAMLized哈希。

但随后Rails5出现并ActionController::Parameters no longer inherits from Hash

  
      
  • ActionController::Parameters不再继承自HashWithIndifferentAccess
  •   

并在to_h上调用to_hashActionController::Parameters现在会引发异常。

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

serialize :h, Hash

然后模型将从h加载文本,解析YAML以获取ActionController::Parameters实例,并在其上调用to_h以确保它具有哈希,并且您获得例外。

该怎么做

您需要做几件事:

  1. 修复您的控制器,确保它们从params中获得真正的哈希值。
  2. 修复您的数据,以便序列化哈希而不是ActionController::Parameters个实例。
  3. 修复控制器是一个简单的问题,就不是真正哈希值的参数调用to_unsafe_h

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

    我还强烈建议您在那里停止使用serializeserialize有点像kludge,并且没有理智的方式在数据库中使用YAML;由于PostgreSQL和MySQL都支持原生JSON(但我不确定ActiveRecord支持MySQL的JSON有多好),因此也很少需要它。