Ruby on Rails:複数のハッシュキーを削除する


148

私はよくこれを書いています。

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

よりシンプルでクリーンなものはありますか?


2番目のアプローチが適切ではないと書いたとき、ハッシュAPIの豊富さを考えると、これにはすでにいくつかのメソッドやイディオムがあり、サルのパッチは必要ないのではないかと思いました。たぶんそうでもない。答えたすべての人に感謝します!
Mark Westling、

3
Hash#exceptはまさに私が探していたものでした。私はそれがRailsコア拡張であることを覚えていなかったので、Hash APIでそれが見つからないことに戸惑いました。
Mark Westling

1
厳密に言えば答えはそうですHash#except!Hash#except、行く方法です(params!をいじらないでください)。経験則として、絶対に必要な場合を除いて、オブジェクトをインプレースでいじらないでください。副作用によって予期しない結果が生じる可能性があります。
tokland 2013

回答:


219

私はあなたがハッシュを知らないことを推測している#exceptActiveSupportがHashに追加するHashメソッドに。

これにより、コードを次のように簡略化できます。

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

また、Railsチームがパッチを作成したので、モンキーパッチを適用する必要はありません。


1
ああ、私はこれを以前に見たことがあると知っていましたが、どこにいたのか思い出せませんでした!(それで私の「これは正しくない」という発言。)ありがとう!
Mark Westling、

3
それほど文書化されていない方法の1つ。こんなこと探して答えを出してみましたが見当たりませんでした。
tadman 2009年

1
何らかの理由で動作しませんでした。しかしexcept!そうした。Rails 3.0

4
Rails 3.2のActiveRecord属性では、キーに文字列を使用する必要がありましたか?つまり、User.attributes.except("id", "created_at", "updated_at")シンボルは機能しませんでした
house9

1
@ house9の説明に加えて、ActiveRecord attributesメソッドはのHashキーを持つを返しますString。したがって、では文字列キー名を使用する必要があります.except()。私が使用してこれを動き回るしかし、Hash.symbolize_keysア・ラ・@user.attributes.symbolize_keys.except(:password, :notes)使用- symbolize_keys予想されるようにそれが動作可能に
FireDragon

44

を使用Hash#exceptすると問題が処理されますが、潜在的なセキュリティ問題が発生することに注意してください。訪問者からのデータを処理するための良い目安は、ホワイトリストアプローチを使用することです。この場合、Hash#slice代わりに使用します。

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

1
リダイレクトに関するセキュリティの問題に言及していただきありがとうございます。
David J.

12
ほんの少し前に:Ruby自体ではなくActiveSupportがHash#sliceと#sliceを提供します!as.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/...
デヴィッド・J.

1
David Jamesのリンクを機能させることができませんでしたが、これは問題ないようです:api.rubyonrails.org/classes/Hash.html#method-i-slice
Dominic Sayers

未定義のメソッド 'slice!' for{:b=>2, :c=>3}:Hash
Khurram Raza

25

質問で最初に投稿したコードに完全に満足します。

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

変更することなく、Hash1:これが最善の答えは
ダン・ブラッドベリ

私はこの方法を使用しましたが、paramsをハッシュの名前に置き換え、それが機能しました!! ハッシュは変化します。
Pablo


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

5
モンキーパッチは最後の手段です。
Bob Aman、

15
既存の機能を置き換えるサルのパッチは、最後の手段です。新しい機能を追加モンキーパッチは、Ruby 101ある
デヴィッド・ザイラー

4
する必要がありますdelete(k)代わりにdelete(key)
ヴィンセント

コードメンテナンスの場合、非破壊的な実装はdelete_keys単純にする必要がありますdup.delete_keys!(*keys)
Phrogz

@Phrogz片方をもう片方で定義することは必ずしも悪い考えではありませんが、明確にするためにここでは展開しないでおきます。
tadman 2015

2

提案されたソリューションのどこが悪いと思うかわかりません。あなたdelete_allはハッシュか何かのメソッドが欲しいと思いますか?もしそうなら、タッドマンの答えは解決策を提供します。しかし、率直に言って、1回限りの場合、あなたのソリューションは非常に簡単に理解できると思います。これを頻繁に使用する場合は、ヘルパーメソッドでラップすることをお勧めします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.