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

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

13.10.2009 14:25:03
Когда я писал, что второй подход был неправильным, я имел в виду, что, учитывая богатство Hash API, я подозревал, что для этого уже есть какой-то метод или идиома, и обезьяна-патч не понадобится. Может быть, нет. Большое спасибо всем, кто ответил!
Mark Westling 13.10.2009 15:08:28
Hash # кроме того, что я искал. Я не помнил, что это расширение ядра Rails, поэтому я был озадачен, когда не смог найти его в Hash API.
Mark Westling 13.10.2009 16:15:59
Обратите внимание, что строго ответ, Hash#except!но Hash#exceptэто путь (не связывайтесь params!). Как правило, не связывайтесь с какими-либо объектами на месте, если это абсолютно не требуется, побочные эффекты могут иметь неожиданные результаты.
tokland 19.08.2013 11:36:04
6 ОТВЕТОВ
РЕШЕНИЕ

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

Это позволило бы упростить ваш код до:

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

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

219
22.05.2014 14:51:17
Аааа, я знал, что видел это раньше, но я не мог вспомнить, где! (Следовательно, мое замечание «это не правильно».) Спасибо!
Mark Westling 13.10.2009 16:10:13
Один из тех менее документированных методов. Я искал что-то подобное, предлагая ответ, но не видел его.
tadman 13.10.2009 21:41:21
По какой-то причине кроме не работал. Но except!сделал. Rails 3.0
Trip 17.08.2012 16:53:36
Rails 3.2 на атрибутах ActiveRecord, пришлось использовать строки для ключей? т.е. User.attributes.except("id", "created_at", "updated_at")символы не работали
house9 18.12.2012 18:18:27
В дополнение к тому, что упоминалось @ house9, attributesметод ActiveRecord возвращает Hashключ с ключами, которые есть String. Тогда вам придется использовать имена строковых ключей в .except(). Однако я Hash.symbolize_keys@user.attributes.symbolize_keys.except(:password, :notes)symbolize_keys
FireDragon 8.01.2020 01:18:03

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

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
8
18.02.2014 21:14:10
Обезьяны патчи являются инструментом последней инстанции.
Bob Aman 13.10.2009 15:29:41
Обезьяны, которые заменяют существующие функции, являются последним средством. Патчи Monkey, которые добавляют новые функции - это Ruby 101.
David Seiler 13.10.2009 15:33:09
Должно быть delete(k)вместоdelete(key)
Vincent 29.12.2010 02:26:23
Для обслуживания кода реализация неразрушающего delete_keysдолжна быть простоdup.delete_keys!(*keys)
Phrogz 20.04.2015 21:18:52
@Phrogz Определение одного в терминах другого не всегда плохая идея, но для ясности его просто оставили здесь развернутым.
tadman 21.04.2015 15:53:50

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

2
23.05.2017 10:31:19

Другой способ сформулировать ответ дматью:

params.delete_if { |k,v| [:controller, :action, :other_key].include? k }
13
29.07.2013 16:23:42

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

[:controller, :action, :other_key].each { |k| params.delete(k) }
25
13.10.2009 15:32:28
без изменений Hashэто лучший ответ: +1:
Dan Bradbury 1.02.2016 20:53:01
Я использовал этот метод, но заменил params на имя хэша, и тогда это сработало !! Хеш видоизменяется.
Pablo 24.02.2019 18:28:15

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

params.slice!(:param_to_remove_1, :param_to_remove_2)
redirect_to my_path(params)
44
24.01.2017 14:55:50
Спасибо за упоминание проблем безопасности, связанных с перенаправлением.
David J. 4.02.2011 19:14:00
Просто наперед: ActiveSupport, а не сам Ruby, предоставляет Hash # slice и #slice! as.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/…
David J. 4.02.2011 19:34:34
Я не смог получить ссылку Дэвида Джеймса на работу, но, похоже, с ней все в порядке: api.rubyonrails.org/classes/Hash.html#method-i-slice
Dominic Sayers 22.05.2014 14:47:57
неопределенный метод 'slice!' для{:b=>2, :c=>3}:Hash
Khurram Raza 15.04.2019 08:35:57