Ruby on Rails: Usuń wiele kluczy mieszających


148

Często piszę to:

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

Ścieżka usuwania nie wydaje się odpowiednia, podobnie jak:

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

Czy jest coś prostszego i czystszego?


Kiedy pisałem, że drugie podejście nie wydaje się właściwe, miałem na myśli, że biorąc pod uwagę bogactwo Hash API, podejrzewałem, że istnieje już jakaś metoda lub idiom do tego i małpa łatka nie byłaby konieczna. Może jednak nie. Wielkie dzięki dla wszystkich, którzy odpowiedzieli!
Mark Westling

3
Hash # z wyjątkiem był dokładnie tym, czego szukałem. Nie pamiętałem, że jest to podstawowe rozszerzenie Railsów, więc byłem zdziwiony, gdy nie mogłem go znaleźć w Hash API.
Mark Westling

1
Zwróć uwagę, że odpowiedź brzmi, Hash#except!ale Hash#exceptjest drogą do zrobienia (nie zadzieraj params!). Z reguły nie rób bałaganu z żadnym obiektem na miejscu, chyba że jest to absolutnie wymagane, ponieważ efekty uboczne mogą mieć nieoczekiwane rezultaty.
tokland

Odpowiedzi:


219

Domyślam się, że nie jesteś świadomy Hash # z wyjątkiem metody ActiveSupport, która dodaje do Hash.

Pozwoliłoby to na uproszczenie kodu do:

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

Nie musiałbyś też małpować łatek, ponieważ zespół Rails zrobił to za Ciebie!


1
Ahhh, wiedziałem, że już to widziałem, ale nie pamiętałem gdzie! (Stąd moja uwaga „to nie jest właściwe”.) Dzięki!
Mark Westling

3
Jedna z tych mniej udokumentowanych metod. Szukałem czegoś takiego, proponując odpowiedź, ale jej nie widziałem.
tadman

1
Z jakiegoś powodu, z wyjątkiem tego, że nie zadziałało. Ale except!zrobił. Rails 3.0
Trip

4
Railsy 3.2 na atrybutach ActiveRecord, musiały używać ciągów znaków dla kluczy? tzn. User.attributes.except("id", "created_at", "updated_at")symbole nie działały
house9

1
Dodając do tego, o czym wspomniał @ house9, attributesmetoda ActiveRecord zwraca a Hashz kluczami, które są String. Więc wtedy musiałbyś używać nazw kluczy w .except(). Jednak Hash.symbolize_keys@user.attributes.symbolize_keys.except(:password, :notes)symbolize_keys
omijam

44

Podczas używania Hash#exceptrozwiązuje problem, pamiętaj, że wprowadza potencjalne problemy z bezpieczeństwem . Dobrą praktyczną zasadą postępowania z danymi od odwiedzających jest użycie metody białej listy. W tym przypadku użycie Hash#slicezamiast.

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

1
Dziękujemy za wspomnienie o problemach z bezpieczeństwem związanych z przekierowaniem.
David J.

12
Tylko jedno ostrzeżenie: ActiveSupport, a nie sam Ruby, zapewnia Hash # slice i #slice! as.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/…
David J.

1
Nie mogłem pobrać linku Davida Jamesa do pracy, ale ten wydaje się być w porządku: api.rubyonrails.org/classes/Hash.html#method-i-slice
Dominic Sayers

niezdefiniowana metoda „plasterek!” dla{:b=>2, :c=>3}:Hash
Khurram Raza

25

Byłbym całkowicie zadowolony z kodu, który zamieściłeś w swoim pytaniu.

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

bez modyfikowania Hashto najlepsza odpowiedź: +1:
Dan Bradbury

Użyłem tej metody, ale zamieniłem parametry na nazwę skrótu i ​​zadziałało !! Skrót zostaje zmutowany.
Pablo

13

Innym sposobem wyrażenia odpowiedzi dmathieu może być

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

8

Odpalić małpę?

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
Plasterki małp są narzędziem ostatniej szansy.
Bob Aman

15
Łatki Monkey, które zastępują istniejące funkcje, są narzędziem ostatniej szansy. Łatki Monkey, które dodają nowe funkcje, to Ruby 101.
David Seiler

4
Powinien być delete(k)zamiastdelete(key)
Vincent

Aby delete_keyszachować kod, implementacja nieniszczącej powinna być prostadup.delete_keys!(*keys)
Phrogz

@Phrogz Definiowanie jednego w kategoriach drugiego nie zawsze jest złym pomysłem, ale dla jasności zostało to po prostu rozwinięte.
tadman

2

Nie wiem, co Twoim zdaniem jest niewłaściwe w proponowanym rozwiązaniu. Przypuszczam, że chcesz delete_allmetodę na Hash czy coś? Jeśli tak, odpowiedź Tadmana dostarcza rozwiązania. Ale szczerze, jednorazowo, myślę, że twoje rozwiązanie jest niezwykle łatwe do zastosowania. Jeśli używasz tego często, możesz chcieć zawrzeć to w metodzie pomocniczej.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.