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

더 간단하고 깨끗한 것이 있습니까?


두 번째 접근법이 옳지 않다고 썼을 때, 나는 Hash API가 풍부하기 때문에 이미 거기에 대한 방법이나 관용구가 있다고 생각했고 원숭이 패치가 필요하지 않을 것이라고 생각했습니다. 그래도 아닐 수도 있습니다. 답변 해 주신 모든 분들께 감사드립니다!
Mark Westling

3
해시 # 제외는 내가 찾던 것입니다. 나는 그것이 Rails 코어 확장이라는 것을 기억하지 못했기 때문에 Hash API에서 찾을 수 없을 때 당황했습니다.
Mark Westling

1
엄밀히 대답은 Hash#except!있지만 Hash#except갈 길입니다 (망설이지 마십시오 params!). 일반적으로 절대적으로 필요한 경우가 아니면 제자리에있는 물체를 엉망으로 만들지 마십시오. 부작용으로 인해 예기치 않은 결과가 발생할 수 있습니다.
tokland

답변:


219

ActiveSupport가 해시에 추가 하는 Hash # except 메서드를 모르는 것 같습니다 .

코드를 다음과 같이 단순화 할 수 있습니다.

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

또한 Rails 팀이 자동으로 패치했기 때문에 원숭이 패치가 필요하지 않습니다!


1
아아, 나는 이것을 전에 본 것을 알고 있었다. 그러나 나는 어디에 있는지 기억할 수 없었다! (따라서 나의 "이것이 옳지 않다"고하는 말입니다.) 감사합니다!
Mark Westling

3
덜 문서화 된 방법 중 하나입니다. 나는 대답을 제안하면서 이와 같은 것을 찾았지만 보지 못했습니다.
tadman

1
어떤 이유로 든 작동하지 않았습니다. 그러나 except!않았다. 레일스 3.0
트립

4
ActiveRecord 속성에 대한 Rails 3.2, 키에 문자열을 사용해야 했습니까? 즉 User.attributes.except("id", "created_at", "updated_at")기호가 작동하지 않습니다
house9

1
@ house9가 언급 한 것에 덧붙여 ActiveRecord attributes메서드는 Hashwith 키를 반환합니다 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/…
David J.

1
나는 David James의 링크를 작동시킬 수 없었지만 이것은 좋아 보인다 : api.rubyonrails.org/classes/Hash.html#method-i-slice
Dominic Sayers

정의되지 않은 메소드 'slice!' 대한{:b=>2, :c=>3}:Hash
Khurram 라자

25

귀하의 질문에 원래 게시 한 코드에 완전히 만족합니다.

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

수정하지 않고 Hash이것이 가장 좋은 답변입니다 : +1 :
Dan Bradbury

나는이 방법을 사용했지만 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입니다.
David Seiler

4
delete(k)대신 해야합니다delete(key)
Vincent

코드 유지 관리를 위해 비파괴 구현은 delete_keys간단해야합니다.dup.delete_keys!(*keys)
Phrogz

@Phrogz 하나를 다른 것의 관점에서 정의하는 것이 항상 나쁜 생각은 아니지만 명확성을 위해 여기에 풀려 있습니다.
tadman

2

제안한 솔루션에 어떤 문제가 있다고 생각하는지 모르겠습니다. delete_all해시 또는 다른 방법 을 원한다고 가정하십시오 . 그렇다면 tadman의 답변 이 해결책을 제공합니다. 그러나 솔직히 말하면 귀하의 솔루션은 매우 쉽게 따라 할 수 있다고 생각합니다. 이것을 자주 사용하는 경우 도우미 방법으로 마무리해야 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.