HashWithIndifferentAccess не работает с оператором формата% в Rails 5 - PullRequest
3 голосов
/ 22 июня 2019

Метод строки Ruby % позволяет заменить заполнители имен значениями данного хэша: "Hello %{name}" % {name: "World"} приведет к "Hello World".

Проблема в том, что он не работает с HashWithIndifferentAccess аргументами.В Rails 5 этот код вызвал бы исключение:

2.3.8 :001 > "%{a}" % {"a" => 1}.with_indifferent_access
KeyError: key{a} not found
    from (irb):1:in `%'
    from (irb):1

Интересно также, что тот же код прекрасно работает в Rails 4, но не в Rails 5

Есть ли способ исправить это (может быть, какое-то исправление обезьяны ActiveSupport::HashWithIndifferentAccess) и понять, почему изменилось поведение %sprintf тоже)?

1 Ответ

2 голосов
/ 23 июня 2019

Это происходит главным образом из-за изменений, внесенных в ActiveSupport::HashWithIndifferentAccess в различных выпусках по мере развития Rails, и в метод default (не путайте с Hash # default).

Если вы видите в Rails 4 версию ActiveSupport :: HashWithIndifferentAccess, метод по умолчанию будет выглядеть так:

def default(key = nil)
  if key.is_a?(Symbol) && include?(key = key.to_s)
    self[key]
  else
    super
  end
end

Который явно получает ключ при вызове, проверяет его тип и, если включен в хеш (self) в качестве одного из ключей, возвращает его значение, в противном случае вызывает super.

А в более новых версиях (более новых, потому что ваш пример не работает в версиях Rails 4+) это выглядит так:

def default(*args)
  super(*args.map { |arg| convert_key(arg) })
end

def convert_key(key) # :doc:
  key.kind_of?(Symbol) ? key.to_s : key
end

Который пытается вернуть каждый элемент из аргументов, переданных по умолчанию, при вызове String, если это символ, или вернуть тот же элемент.

Это в вашем примере вернет nil для default, что объясняет ошибку KeyError, которую вы получаете.

Ошибка или разница в поведении не %, а во внесенных изменениях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...