Ruby on Rails: Löschen Sie mehrere Hash-Schlüssel


148

Ich schreibe oft Folgendes:

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

Die Spur der Löschungen fühlt sich nicht richtig an und auch nicht:

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

Gibt es etwas einfacheres und saubereres?


Als ich schrieb, dass sich der zweite Ansatz nicht richtig anfühlte, meinte ich, dass ich angesichts des Reichtums der Hash-API vermutete, dass es dafür bereits eine Methode oder Redewendung gibt und ein Affen-Patch nicht notwendig wäre. Vielleicht aber auch nicht. Vielen Dank an alle, die geantwortet haben!
Mark Westling

3
Hash # außer war genau das, wonach ich gesucht habe. Ich habe mich nicht daran erinnert, dass es sich um eine Rails-Kernerweiterung handelt, daher war ich verwirrt, als ich sie in der Hash-API nicht finden konnte.
Mark Westling

1
Beachten Sie, dass genau die Antwort ist, Hash#except!aber Hash#exceptder richtige Weg ist (spielen Sie nicht mit params!). Als Faustregel gilt, dass Sie mit keinem Objekt an Ort und Stelle herumspielen dürfen, es sei denn, dies ist unbedingt erforderlich. Die Nebenwirkungen können zu unerwarteten Ergebnissen führen.
Tokand

Antworten:


219

Ich vermute, Sie kennen die Hash-Nummer nur Methode, die ActiveSupport zu Hash hinzufügt.

Dadurch kann Ihr Code vereinfacht werden, um:

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

Außerdem müssten Sie keinen Affen-Patch ausführen, da das Rails-Team dies für Sie erledigt hat!


1
Ahhh, ich wusste, dass ich das schon einmal gesehen hatte, aber ich konnte mich nicht erinnern, wo! (Daher meine Bemerkung "Das fühlt sich nicht richtig an".) Danke!
Mark Westling

3
Eine dieser weniger dokumentierten Methoden. Ich suchte nach so etwas, während ich eine Antwort vorschlug, sah sie aber nicht.
Tadman

1
Aus irgendeinem Grund außer hat nicht funktioniert. Aber except!tat es. Rails 3.0
Trip

4
Musste Rails 3.2 für ActiveRecord-Attribute Zeichenfolgen für die Schlüssel verwenden? dh User.attributes.except("id", "created_at", "updated_at")Symbole funktionierten nicht
house9

1
Zusätzlich zu dem, was @ house9 erwähnt hat, attributesgibt die ActiveRecord- Methode a Hashmit Schlüsseln zurück, die sind String. Dann müssten Sie also String-Schlüsselnamen in verwenden .except(). Ich komme jedoch mit dem Hash.symbolize_keysa la @user.attributes.symbolize_keys.except(:password, :notes)- using symbolize_keys
darum

44

Beachten Sie bei der Verwendung Hash#exceptIhres Problems, dass dadurch potenzielle Sicherheitsprobleme auftreten . Eine gute Faustregel für den Umgang mit Daten von Besuchern ist die Verwendung eines Whitelist-Ansatzes. In diesem Fall mitHash#slice stattdessen.

params.slice!(:param_to_remove_1, :param_to_remove_2)
redirect_to my_path(params)

1
Vielen Dank, dass Sie die Sicherheitsprobleme im Zusammenhang mit der Umleitung erwähnt haben.
David J.

12
Nur ein Kopf hoch: ActiveSupport, nicht Ruby selbst, bietet Hash # Slice und # Slice! as.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/…
David J.

1
Ich konnte David James 'Link nicht zum Laufen bringen,
Dominic Sayers

undefinierte Methode 'Slice!' für{:b=>2, :c=>3}:Hash
Khurram Raza

25

Ich wäre mit dem Code, den Sie ursprünglich in Ihrer Frage gepostet haben, völlig zufrieden.

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

ohne Hash
Dan Bradbury

Ich habe diese Methode verwendet, aber die Parameter durch den Namen des Hashs ersetzt und dann hat es funktioniert !! Der Hash wird mutiert.
Pablo

13

Eine andere Möglichkeit, die Antwort von dmathieu zu formulieren, könnte sein

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

8

Einen Affenfeld anfeuern?

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

5
Affenpflaster sind ein Werkzeug der letzten Instanz.
Bob Aman

15
Affen-Patches , die vorhandene Funktionen ersetzen, sind das letzte Mittel. Affen-Patches, die neue Funktionen hinzufügen, sind Ruby 101.
David Seiler

4
Sollte delete(k)statt seindelete(key)
Vincent

Für die Code-Wartung sollte die Implementierung des zerstörungsfreien delete_keyseinfach seindup.delete_keys!(*keys)
Phrogz

@Phrogz Es ist nicht immer eine schlechte Idee, eines in Bezug auf das andere zu definieren, aber es wird hier aus Gründen der Klarheit nur abgewickelt.
Tadman

2

Ich weiß nicht, was Ihrer Meinung nach mit Ihrer vorgeschlagenen Lösung falsch ist. Ich nehme an, Sie wollen eine delete_allMethode für Hash oder so? Wenn ja, bietet Tadmans Antwort die Lösung. Aber ehrlich gesagt, für eine einmalige Sache denke ich, dass Ihre Lösung extrem einfach zu befolgen ist. Wenn Sie dies häufig verwenden, möchten Sie es möglicherweise in eine Hilfsmethode einbinden.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.