Ruby on Rails: удалить несколько ключей хеша

119

Я часто нахожу, что пишу это:

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

Есть ли что-нибудь более простое и чистое?

  • 0
    Когда я писал, что второй подход не подходит, я имел в виду, что, учитывая богатство Hash API, я подозревал, что для этого уже есть какой-то метод или идиома, и патч для обезьяны не понадобится. Может быть, нет. Большое спасибо всем, кто ответил!
  • 3
    Hash # кроме того, что я искал. Я не помнил, что это расширение ядра Rails, поэтому я был озадачен, когда не смог найти его в Hash API.
Показать ещё 1 комментарий
Теги:

6 ответов

185
Лучший ответ

Я предполагаю, что вы не знаете о Hash # except метод ActiveSupport добавляет к Hash.

Это упростит ваш код:

redirect_to my_path(params.except(:controller, :action, :other_key))

Кроме того, у вас не было бы патча обезьяны, так как команда Rails сделала это для вас!

  • 1
    Аааа, я знал, что видел это раньше, но я не мог вспомнить, где! (Отсюда мое замечание «это не правильно».) Спасибо!
  • 0
    Острота! Надо запомнить это.
Показать ещё 6 комментариев
40

При использовании Hash#except устраняет вашу проблему, имейте в виду, что она представляет потенциальные проблемы безопасности. Хорошим правилом для обработки любых данных от посетителей является использование белого списка. В этом случае вместо этого используйте Hash#slice.

params.slice!(:param_to_remove_1, :param_to_remove_2)
redirect_to my_path(params)
  • 1
    Спасибо за упоминание проблем безопасности, связанных с перенаправлением.
  • 12
    Просто наперед: ActiveSupport, а не сам Ruby, предоставляет Hash # slice и #slice! as.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/...
Показать ещё 1 комментарий
19

Я был бы полностью доволен кодом, который вы изначально разместили в своем вопросе.

[:controller, :action, :other_key].each { |k| params.delete(k) }
  • 0
    без изменения Hash это лучший ответ: +1:
  • 0
    Я использовал этот метод, но заменил params на имя хэша, и тогда это сработало !! Хеш видоизменяется.
9

Другим способом выражения ответа dmathieu может быть

params.delete_if { |k,v| [:controller, :action, :other_key].include? k }
  • 2
    Я думаю, что вы имеете в виду params.delete_if { |k, v| [:controller, :action, :other_key].include? k }
  • 0
    Хороший улов, Телемах.
8

Запустите патч обезьяны?

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
  • 4
    Обезьяны патчи являются инструментом последней инстанции.
  • 14
    Обезьяны, которые заменяют существующие функции, являются последним средством. Патчи Monkey, которые добавляют новые функции - это Ruby 101.
Показать ещё 3 комментария
2

Я не знаю, что вы считаете неправильным в своем предлагаемом решении. Я полагаю, вы хотите использовать метод delete_all для Hash или что-то еще? Если да, то ответ tadman предоставляет решение. Но, честно говоря, для одноразового, я думаю, ваше решение очень легко следовать. Если вы используете это часто, вы можете его обернуть в вспомогательном методе.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню