Ruby on Rails: Birden çok karma anahtarını sil


148

Kendimi genellikle bunu yazarken buluyorum:

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

Silmenin izi doğru gelmiyor ve ikisi de:

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

Daha basit ve daha temiz bir şey var mı?


İkinci yaklaşımın iyi hissetmediğini yazdığımda, Hash API'sinin zenginliği göz önüne alındığında, bunun için zaten bir yöntem veya deyim olduğundan şüpheliydim ve bir maymun yaması gerekli olmayacaktı. Belki de değil. Cevap veren herkese çok teşekkürler!
Mark Westling

3
Hash # dışında tam olarak aradığım şeydi. Bir Rails çekirdek uzantısı olduğunu hatırlamadım, bu yüzden Hash API'sinde bulamadığımda şaşkındım.
Mark Westling

1
Kesinlikle cevap olduğunu unutmayın Hash#except!ama Hash#exceptgitmek için yol (ile uğraşmak yok params!). Genel bir kural olarak, kesinlikle gerekli olmadıkça yerinde herhangi bir nesneyle uğraşmayın, yan etkilerin beklenmedik sonuçları olabilir.
tokland

Yanıtlar:


219

ActiveSupport'un Hash'e eklediği yöntem dışında Hash # öğesinin farkında olmadığınızı tahmin ediyorum .

Kodunuzun basitleştirilmesine izin verir:

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

Ayrıca, Rails ekibi sizin için yaptığı için maymun yaması yapmak zorunda kalmazsınız!


1
Ahhh, bunu daha önce gördüğümü biliyordum ama nerede olduğunu hatırlayamadım! (Bu yüzden "bu doğru gelmiyor" sözlerim.) Teşekkürler!
Mark Westling

3
Daha az belgelenmiş yöntemlerden biri. Bir cevap teklif ederken böyle bir şey aramaya gittim ama görmedim.
tadman

1
Bir sebepten ötürü işe yaramadı. Ama except!yaptı. Raylar 3.0
Yolculuk

4
Rails 3.2 ActiveRecord öznitelikleri, anahtarlar için dizeleri kullanmak zorunda mıydı? yani User.attributes.except("id", "created_at", "updated_at")semboller işe yaramadı
house9

1
@ House9'un bahsettiğine ek olarak, ActiveRecord attributesyöntemi Hashanahtarları olan bir a döndürür String. Bu nedenle, dize anahtar adlarını kullanmanız gerekir .except(). Ancak ben bunu kullanarak Hash.symbolize_keysbir la @user.attributes.symbolize_keys.except(:password, :notes)- kullanarak symbolize_keysbeklendiği gibi çalışır yapar
FireDragon

44

Kullanırken Hash#exceptsorununuzu çözerken, olası güvenlik sorunlarını ortaya çıkardığını unutmayın . Ziyaretçilerden herhangi bir verinin işlenmesi için iyi bir kural, beyaz liste yaklaşımı kullanmaktır. Bu durumda, Hash#slicebunun yerine.

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

1
Yeniden yönlendirmeyi çevreleyen güvenlik sorunlarından bahsettiğiniz için teşekkür ederiz.
David J.

12
Sadece bir adım yukarı: ActiveSupport, Ruby'nin kendisi değil, Hash # dilimi ve # dilim sağlar! as.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/…
David J.

1
David James'in linkini çalıştıramadım ama bu iyi görünüyor: api.rubyonrails.org/classes/Hash.html#method-i-slice
Dominic Sayers

undefined yöntemi 'dilim!' için{:b=>2, :c=>3}:Hash
Khurram Raza

25

Sorunuza orijinal olarak gönderdiğiniz koddan tamamen memnun olurum.

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

değiştirmeden Hashbu en iyi cevaptır: +1:
Dan Bradbury

Bu yöntemi kullandım ama params karma adı ile değiştirildi ve sonra çalıştı! Karma mutasyona uğrar.
Pablo

13

Dmathieu'nun cevabını ifade etmenin başka bir yolu da

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

8

Maymun yamasını ateşlemek mi?

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
Maymun yamaları son çare aracıdır.
Bob Aman

15
Mevcut işlevlerin yerini alan maymun yamaları son çare aracıdır. Yeni işlevler ekleyen maymun yamaları Ruby 101.
David Seiler

4
Bunun delete(k)yerinedelete(key)
Vincent

Kod bakımı için tahribatsızın delete_keysuygulanması basit olmalıdırdup.delete_keys!(*keys)
Phrogz

@Phrogz Birini diğeri açısından tanımlamak her zaman kötü bir fikir değildir, ancak burada netlik için açık bırakılmıştır.
tadman

2

Önerilen çözümünüzde neyin yanlış olduğunu düşündüğünüzü bilmiyorum. Sanırım Hash'de bir delete_allyöntem mi istiyorsunuz ? Eğer öyleyse, tadman'ın cevabı çözümü sağlar. Ama açıkçası, bir defalık için, çözümünüzü takip etmek son derece kolay. Bunu sık sık kullanıyorsanız, yardımcı bir yöntemle tamamlamak isteyebilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.