159 votes

Ruby on Rails : Supprimer plusieurs clés de hachage

Je me retrouve souvent à écrire cela :

params.delete(:controller)  
params.delete(:action)  
params.delete(:other_key)  
redirect_to my_path(params)  

La traînée de suppressions ne semble pas correcte, et elle ne l'est pas non plus :

[:controller, :action, :other_key].each do |k|
  params.delete(k)
end

Y a-t-il quelque chose de plus simple et de plus propre ?

0 votes

Lorsque j'ai écrit que la deuxième approche ne me semblait pas correcte, je voulais dire qu'étant donné la richesse de l'API Hash, je soupçonnais qu'il existait déjà une méthode ou un idiome pour cela et qu'un patch pour les singes ne serait pas nécessaire. Peut-être pas, cependant. Merci beaucoup à tous ceux qui ont répondu !

3 votes

Hash#except était exactement ce que je cherchais. Je ne me souvenais pas qu'il s'agissait d'une extension du noyau de Rails. J'ai donc été étonné de ne pas la trouver dans l'API Hash.

2 votes

Notez que la réponse stricte est Hash#except! pero Hash#except est la meilleure solution (ne pas utiliser la fonction params !). En règle générale, ne modifiez pas un objet en place à moins que cela ne soit absolument nécessaire, les effets secondaires peuvent avoir des résultats inattendus.

236voto

Ben Points 5341

Je suppose que vous n'êtes pas au courant de la Hash#except ActiveSupport ajoute une méthode à Hash.

Cela permettrait de simplifier votre code à :

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

De plus, vous n'auriez pas à faire de patch singulier, puisque l'équipe Rails l'a fait pour vous !

1 votes

Ahhh, je savais que j'avais déjà vu ça avant mais je ne me souvenais pas où ! (D'où ma remarque "ça ne me semble pas correct".) Merci !

3 votes

Une de ces méthodes moins documentées. J'ai cherché quelque chose comme ça en proposant une réponse mais je ne l'ai pas vu.

1 votes

Pour une raison quelconque, sauf que ça n'a pas marché. Mais except! a fait. Rails 3.0

46voto

En utilisant Hash#except gère votre problème, sachez qu'il introduit les problèmes de sécurité potentiels . Une bonne règle de base pour traiter les données des visiteurs est d'utiliser une liste blanche. Dans ce cas, l'utilisation de Hash#slice à la place.

params.slice!(:param_to_keep_1, :param_to_keep_2)
redirect_to my_path(params)

28voto

Bob Aman Points 19110

Je serais tout à fait satisfait du code que vous avez posté dans votre question.

[:controller, :action, :other_key].each { |k| params.delete(k) }

0 votes

Sans modifier Hash C'est la meilleure réponse :+1 :

0 votes

J'ai utilisé cette méthode mais j'ai remplacé params par le nom du hash et ça a marché ! Le hash est muté.

15voto

MikeSep Points 3013

Une autre façon de formuler la réponse de dmathieu pourrait être

params.delete_if { |k,v| [:controller, :action, :other_key].include? k }

7voto

tadman Points 70178

Allumer un patch de singe ?

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

6 votes

Les patchs pour singes sont un outil de dernier recours.

15 votes

Taches de singe qui remplacent des fonctions existantes sont un outil de dernier recours. Les rustines de singe qui ajoutent de nouvelles fonctions sont Ruby 101.

4 votes

Devrait être delete(k) au lieu de delete(key)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X