Not_nil için Ruby veya Ruby-ism var mı? sıfırın tersi? yöntem?


87

Ruby konusunda deneyimli değilim, bu yüzden kodum "çirkin" geliyor ve deyimsel değil:

def logged_in?
  !user.nil?
end

Gibi bir şeyi tercih ederim

def logged_in?
  user.not_nil?
end

Ama zıtlıkların olduğu böyle bir yöntem bulamıyorum nil?

Yanıtlar:


50

ActiveSupport kullanırken, yalnızca sıfır olmayanları kontrol etmek için user.present? http://api.rubyonrails.org/classes/Object.html#method-i-present%3F var , neden kullanmayasınız?

def logged_in?
  user # or !!user if you really want boolean's
end

48
Dikkat: present?boş olmayan bir dize gerektirir. ! "".nil?true döndürür, ancak "".present?false döndürür.
lambshaanxy

9
Dikkat 2: Ayrıca !! kullanıcısının, kullanıcının sıfır ve kullanıcının yanlış olduğunu ayırt etmediğini de not edeceğim; çift ​​patlama kullanımı bu ikisini birleştirir. Dolayısıyla, bir nesnenin sıfır olup olmadığını gerçekten belirlemek istiyorsanız (yani: true, false, 0, "", sıfır dışında herhangi bir şey), berkes'in sevmediği "çirkin" yaklaşımı kullanmanız gerekir. veya @Tempus'un aşağıda önerdiği monkeypatch . Nil değil bu durumda Tabii değil gerekli (Rails bir kullanıcı), Samo tarafından alınan yaklaşım imo, çirkin az olduğunu.
likethesky

12
false.present? == false !false.nil? == true
Dudo

3
Bu cevap, sorulan soruya hiç cevap vermiyor. Bu özel uygulama problemine bir cevaptır.
Ekkstein

3
Bu cevap doğru değil. false.nil? false, false.present iken? AYRICA yanlıştır!
Mike

49

Booleanlarla fazlasıyla ilgileniyor gibisin.

def logged_in?
  user
end

Kullanıcı nil ise, logged_in? bir "yanlış" değeri döndürür. Aksi takdirde, bir nesne döndürür. Ruby'de, JavaScript'te olduğu gibi "doğru" ve "yanlış" değerlere sahip olduğumuz için doğru veya yanlış döndürmemize gerek yoktur.

Güncelleme

Rails kullanıyorsanız, present?yöntemi kullanarak bunu daha güzel bir şekilde okumasını sağlayabilirsiniz :

def logged_in?
  user.present?
end

1
A ile biten bir yöntemin beklentisi, ?bir boole döndürmesidir. !!valueherhangi bir şeyi mantıksal değere dönüştürmenin klasik yoludur. Tam olarak aynı değil, ancak bu durumda Object#present?RoR'da da iyi.
tokland

bu aslında Yol ile Ruby 2.4'te bozulur! [43] (gözetleme) # <ReactOnRails :: AssetsPrecompile>: 0> assets_path.blank? true [44] (pry) # <ReactOnRails :: AssetsPrecompile>: 0> assets_path.to_s "/ var / klasörler / rp / _k99k0pn0rsb4d3lm9l3dnjh0000gn / T / d20170603-96466-zk7di7" [45] (pryRails) >: 0> assets_path.present? false [46] (gözetlemek) # <ReactOnRails :: AssetsPrecompile>: 0> assets_path.nil? false
justingordon

26

present?Sorunuzun cevabı olarak sunulan diğer cevaplara dikkat edin .

present?blank?rayların tersidir .

present?anlamlı bir değer olup olmadığını kontrol eder. Bunlar bir present?kontrolde başarısız olabilir :

"".present? # false
"    ".present? # false
[].present? # false
false.present? # false
YourActiveRecordModel.where("false = true").present? # false

Bir !nil?çek ise:

!"".nil? # true
!"    ".nil? # true
![].nil? # true
!false.nil? # true
!YourActiveRecordModel.where("false = true").nil? # true

nil?bir nesnenin gerçekten olup olmadığını kontrol eder nil. Başka herhangi bir şey: boş bir dize 0,false , neyse değildir nil.

present? çok kullanışlıdır, ancak kesinlikle tersi değildir nil? . İkisini karıştırmak beklenmedik hatalara yol açabilir.

Kullanım durumunuz present?işe yarayacaktır, ancak farkın farkında olmak her zaman akıllıca olacaktır.


Kabul edilen cevaba dahil edilmelidir. false.blank?ile aynı değilfalse.nil?
Yason

present?veritabanınızı sorgulayacak nil?, buna dikkat etmeyecek
Tony

17

Belki bu bir yaklaşım olabilir:

class Object
  def not_nil?
    !nil?
  end
end

İyi bir fikir. Bundan not_nil olmadığını anlıyorum? Ruby'de. Ama bu o zaman !self.nil?daha ziyade olmamalı mı !nil?yoksa selfüstü kapalı mı?
berkes

3
Kendine ihtiyacın yok. İma edilecek.
Geo

Örnek yöntemlerden (veya erişimcilerden, bunlar gerçekten yalnızca yöntemlerden) okurken kendilik ima edilir. Değerleri ayarlarken, metoda yerel bir değişken, Ruby sınıf örneğini aynı isimli bir setter metodu için kontrol etmeden önce oluşturulacaktır. Genel kural: xxx adında bir attr_accessor varsa, "self.xxx = 3" (bir değer belirleyerek) veya "temp = xxx" (değeri okurken) kullanın. "Xxx = 3" kullanılması erişimciyi güncellemeyecektir, sadece yöntem kapsamında yeni bir değişken oluşturun.
A Fader Darkly

5

!Yöntemden elde edilen sonuç üzerine Ruby-esque yöntemini sunabilir miyim nil??

def logged_in?
  user.nil?.!
end

O kadar ezoterik ki RubyMine IDE bunu bir hata olarak işaretleyecektir. ;-)


4

Aşağıdakileri kullanabilirsiniz:

if object
  p "object exists"
else
  p "object does not exist"
end

Bu sadece nil için değil, aynı zamanda yanlış vb. İçin de işe yarar, bu nedenle kullanım durumunuzda işe yarayıp yaramadığını test etmelisiniz.


2

Bu soruya bir nesne yöntemi arayarak ulaştım, böylece bir blok yerine Symbol#to_procsteno kullanabilecektim ; Ben arr.find(&:not_nil?)biraz daha okunaklı buluyorum arr.find { |e| !e.nil? }.

Bulduğum yöntem Object#itself. Kullanımımda, anahtarın karma değerini bulmak istedim name, bazı durumlarda bu anahtarın yanlışlıkla büyük harfle yazıldığı Name. Bu tek satırlık şu şekilde:

# Extract values for several possible keys 
#   and find the first non-nil one
["Name", "name"].map { |k| my_hash[k] }.find(&:itself)

Diğer yanıtlarda da belirtildiği gibi , bu, bir mantıksal değeri test ettiğiniz durumlarda olağanüstü bir şekilde başarısız olacaktır.


Bu nasıl farklı my_hash.values_at("Name", "name").find?
berkes

Tam olarak aynı. Orijinalimde map, bu örnekte basitlik sağlamak için çıkardığım başka bir mantığım vardı , bu nedenle burada yazıldığı gibi değiştirilebilir values_at. Önemli olan, neyin aktarılacağıdır find.
Ian
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.