Почему я получаю сильные ошибки параметров в Rails Console в rails 5?
Я хочу назвать это в моей консоли (ap
это удивительная жемчужина печати):
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
В чем дело?
1 ответ
Что происходит и почему
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
больше не наследует отHash
:
- Делать
ActionController::Parameters
больше не наследует отHashWithIndifferentAccess
,
и звонит to_h
или же to_hash
на ActionController::Parameters
Теперь возникает исключение.
Если вы обновите свой код и попытаетесь загрузить модель с сериализованными данными:
serialize :h, Hash
Затем модель загрузит текст из h
разбери YAML чтобы получить ActionController::Parameters
экземпляр и вызов to_h
на нем, чтобы убедиться, что у него есть хэш, и вы получите исключение.
Что с этим делать
Есть пара вещей, которые вам нужно сделать:
- Исправьте ваши контроллеры, чтобы убедиться, что они получают реальные хэши из
params
, - Исправьте ваши данные так, чтобы вы использовали сериализованные хеши, а не
ActionController::Parameters
экземпляров.
Исправление контроллеров является простым делом вызова to_unsafe_h
на параметры, которые еще не настоящие хэши.
Исправление данных уродливее. Я бы, вероятно, просмотрел таблицы, используя низкоуровневый интерфейс базы данных (т.е. нигде не ActiveRecord), читал YAML из каждой строки, YAML.load
это, преобразовать его в хеш, вызывая to_unsafe_h
на нем, а затем писать обратно the_real_hash.to_yaml
текст. Вы могли бы использовать like '--- !ruby/object:ActionController::Parameters%'
фильтруйте в предложении WHERE, чтобы иметь дело только с разбитыми строками.
Я также настоятельно рекомендую вам прекратить использование serialize
пока ты там. serialize
это немного клудж, и в базе данных нет нормального способа работы с YAML; теперь в этом нет особой необходимости, поскольку и PostgreSQL, и MySQL имеют встроенную поддержку JSON (но я не уверен, насколько хорошо ActiveRecord поддерживает JSON MySQL).