Ruby on Rails: удалить несколько ключей хеша
Я часто пишу это:
params.delete(:controller)
params.delete(:action)
params.delete(:other_key)
redirect_to my_path(params)
След удалений не чувствует себя правильным и не делает:
[:controller, :action, :other_key].each do |k|
params.delete(k)
end
Есть ли что-нибудь попроще и чище?
7 ответов
Я предполагаю, что вы не знаете о Hash#, кроме метода, который ActiveSupport добавляет в Hash.
Это позволило бы упростить ваш код до:
redirect_to my_path(params.except(:controller, :action, :other_key))
Кроме того, вам не нужно будет собирать патчи, поскольку команда Rails сделала это за вас!
При использовании Hash#except
решает вашу проблему, имейте в виду, что это создает потенциальные проблемы безопасности. Хорошее эмпирическое правило для обработки любых данных от посетителей заключается в использовании подхода белого списка. В этом случае, используя Hash#slice
вместо.
params.slice!(:param_to_remove_1, :param_to_remove_2)
redirect_to my_path(params)
Я был бы полностью доволен кодом, который вы изначально разместили в своем вопросе.
[:controller, :action, :other_key].each { |k| params.delete(k) }
Другой способ сформулировать ответ дматью:
params.delete_if { |k,v| [:controller, :action, :other_key].include? k }
Запустить обезьяну?
class Hash
def delete_keys!(*keys)
keys.flatten.each do |k|
delete(k)
end
self
end
def delete_keys(*keys)
_dup = dup
keys.flatten.each do |k|
_dup.delete(k)
end
_dup
end
end
Начиная с Ruby 3.0, поддерживается напрямую. Это означает, что нам не потребуется activesupport для доступа
Hash#except
.
Из документации:
Хэш # кроме (* ключей) → хеш
Этот метод возвращает новый хеш, который включает в себя все из исходного хеша, кроме указанных ключей.
пример:
h = { a: 100, b: 200, c: 300, d: 400 }
h.except(:a, :d) #=> {:b=>200, :c=>300}
Справка:
https://docs.ruby-lang.org/en/3.0.0/Hash.html#method-i-except
Я не знаю, что вы думаете не так с вашим предложенным решением. Я полагаю, вы хотите delete_all
метод по хешу что ли? Если так, то ответ Тэдмана дает решение. Но, честно говоря, для разового, я думаю, что ваше решение очень легко следовать. Если вы используете это часто, вы можете обернуть его вспомогательным методом.