Почему я получаю сильные ошибки параметров в Rails Console в rails 5? - PullRequest
0 голосов
/ 26 мая 2018

Я хочу вызвать это в своей консоли (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 Ответ

0 голосов
/ 26 мая 2018

Что происходит и почему

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.

Но тогда Rails5ActionController::Parameters больше не наследуется от Hash:

  • Make ActionController::Parameters больше не наследуется от HashWithIndifferentAccess.

и вызов to_h или to_hash для ActionController::Parameters теперь вызывает исключение.

Если вы обновляете свой код и пытаетесь загрузить модель с сериализованными данными в нем:

serialize :h, Hash

затем модель загрузит текст из h, проанализирует YAML, чтобы получить экземпляр ActionController::Parameters, и вызовет to_h для него, чтобы убедиться, что у него есть хэш, и вы получите исключение.

Что с этим делать

Есть пара вещей, которые вам нужно сделать:

  1. Исправьте ваши контроллеры, чтобы убедиться, что они получают настоящий хэшs из params.
  2. Исправьте ваши данные таким образом, чтобы вы использовали сериализованные хэши, а не 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).

...