Чи існує Ruby, або Ruby-ism для not_nil? протилежне нулю? метод?


87

Я не маю досвіду роботи в Ruby, тому мій код відчувається "потворним" і не ідіоматичним:

def logged_in?
  !user.nil?
end

Я волів би щось подібне

def logged_in?
  user.not_nil?
end

Але не можу знайти такого методу, який протилежний nil?

Відповіді:


51

коли ви використовуєте ActiveSupport, є user.present? http://api.rubyonrails.org/classes/Object.html#method-i-present%3F , щоб перевірити, чи немає нуля, чому б не використовувати

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

48
Обережно: present?потрібен непустий рядок. ! "".nil?повертає true, але "".present?повертає false.
lambshaanxy

9
Обережно 2: Я також зауважу, що !! користувач НЕ розрізняє користувача як нуля та користувача, який брехає; використання подвійного вибуху поєднує ці два. Отже, якщо ви справді хочете визначити, чи не є об’єкт нульовим (мається на увазі, це: true, false, 0, "", що-небудь, окрім нуля), вам потрібно скористатися "потворним" підходом, який Berkes не любить або мавпа, яку пропонує @Tempus нижче . Звичайно , в цьому випадку , якщо не нуль це НЕ по необхідності (користувач в Rails), підхід , прийнятий Саме найменш некрасиво, ІМО.
likethesky

12
false.present? == false !false.nil? == true
Дудо

3
Ця відповідь зовсім не відповідає на поставлене запитання. Це відповідь на цю конкретну проблему реалізації.
Еккштейн

3
Ця відповідь не правильна. false.nil? є false, тоді як false.present? ТАКОЖ неправда!
Майк

49

Ви здаєтеся надмірно стурбованими логічними значеннями.

def logged_in?
  user
end

Якщо користувач нульовий, то logged_in? поверне значення "фальшивість". В іншому випадку він поверне об’єкт. У Ruby нам не потрібно повертати true або false, оскільки ми маємо значення "неправдиве" та "хибне", як у JavaScript.

Оновлення

Якщо ви використовуєте Rails, ви можете зробити це більш приємним, прочитавши present?метод:

def logged_in?
  user.present?
end

1
Сподівання з методом, який закінчується на a, ?полягає у поверненні логічного значення. !!valueце класичний спосіб перетворити що-небудь на логічну форму. Не зовсім те саме, але в цьому випадку Object#present?в RoR теж добре.
Tokland

це насправді ламається в Ruby 2.4 з Path! [43] (підкажіть) # <ReactOnRails :: AssetsPrecompile>: 0> assets_path.blank? true [44] (підгляньте) # <ReactOnRails :: AssetsPrecompile>: 0> assets_path.to_s "/ var / folders / rp / _k99k0pn0rsb4d3lm9l3dnjh0000gn / T / d20170603-96466-zk7di7" [RealogOnRails] >: 0> assets_path.present? false [46] (підгляньте) # <ReactOnRails :: AssetsPrecompile>: 0> assets_path.nil? false
justingordon

25

Остерігайтеся інших відповідей present? як відповідь на ваше запитання.

present? є протилежністю blank? рейок.

present?перевіряє, чи є значуще значення. Ці речі можуть провалити present?перевірку:

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

Тоді як !nil?перевірка дає:

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

nil?перевіряє, чи є об’єкт насправді nil. Що - небудь ще: порожній рядок, 0, false, що завгодно,nil .

present? дуже корисний, але точно не протилежний nil? . Переплутавши їх, може призвести до несподіваних помилок.

Для вашого випадку використання present?буде працювати, але завжди розумно пам’ятати про різницю.


Повинна бути включена у прийняту відповідь. false.blank?не те саме, щоfalse.nil?
Ясон

present?буде запитувати вашу базу даних, nil?ні, будьте обережні з цим
Тоні

17

Можливо, це може бути підхід:

class Object
  def not_nil?
    !nil?
  end
end

Гарна ідея. Я з цього роблю, що немає not_nil? в Рубі. Але чи не це має бути !self.nil?скоріше тоді !nil?, чи це selfнеявно?
berkes

3
Вам не потрібно себе. Це буде мається на увазі.
Geo

Self розуміється під час читання з методів екземпляра (або аксесуарів, які насправді є лише методами). При встановленні значень буде створена змінна local для методу до того, як Ruby перевірить екземпляр класу на той самий метод методу setter. Загальне правило: якщо у вас є attr_accessor під назвою xxx, використовуйте "self.xxx = 3" (встановлення значення) або "temp = xxx" (читання значення). Використання "xxx = 3" не оновить доступ, просто створіть нову змінну в області методу.
Fader Darkly

4

Ви можете просто використовувати наступне:

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

Це працює не тільки для nil, але і false тощо, тому вам слід перевірити, чи працює це у вашому випадку використання.


4

Можна запропонувати !метод Ruby-esque щодо результатів nil?методу.

def logged_in?
  user.nil?.!
end

Настільки езотеричний, що RubyMine IDE позначить це як помилку. ;-)


2

Я прийшов до цього питання, шукаючи метод об’єкта, щоб я міг використовувати Symbol#to_procскорочення замість блоку; Я вважаю arr.find(&:not_nil?)дещо більш читабельним, ніж arr.find { |e| !e.nil? }.

Я знайшов метод Object#itself. У своєму використанні я хотів знайти значення в хеші для ключа name, де в деяких випадках цей ключ випадково писався з великої літери як Name. Цей однокласник такий:

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

Як зазначалося в інших відповідях , це не вдасться вразити у випадках, коли ви тестуєте логічну форму.


Чим це відрізняється від my_hash.values_at("Name", "name").find?
беркес

Це точно те саме. У моєму оригіналі була інша логіка, mapяку я вилучив для простоти в цьому прикладі, тому, як написано тут, вона взаємозамінна values_at. Важливою є те, на що передається find.
Ян
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.