Есть ли 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?возвращает истину, но "".present?возвращает ложь.
lambshaanxy 07

9
Осторожно 2: я также отмечу, что !! user НЕ различает значение пользователя nil и false; использование двойного взрыва объединяет эти два. Поэтому, если вы действительно хотите определить, не является ли объект нулевым (то есть он: true, false, 0, "", что угодно, кроме nil), вам нужно использовать "уродливый" подход, который не нравится Berkes или обезьяний патч, который @Tempus предлагает ниже . Конечно, в этом случае, когда nil не нужен (пользователь в Rails), подход Само наименее уродлив, imo.
ликетический

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

3
Этот ответ вовсе не отвечает на заданный вопрос. Это ответ на конкретную проблему реализации.
Эккштейн

3
Это неправильный ответ. false.nil? ложно, а ложно. присутствует? ТАКЖЕ ложно!
Майк

49

Вы, кажется, слишком озабочены логическими значениями.

def logged_in?
  user
end

Если пользователь равен нулю, тогда logged_in? вернет значение "ложь". В противном случае он вернет объект. В Ruby нам не нужно возвращать истину или ложь, поскольку у нас есть «истинные» и «ложные» значения, как в JavaScript.

Обновить

Если вы используете Rails, вы можете сделать это лучше, используя present?метод:

def logged_in?
  user.present?
end

1
Ожидается, что метод, заканчивающийся на a ?, вернет логическое значение. !!valueэто классический способ преобразовать что угодно в логическое значение. Не совсем то же самое, но в данном случае Object#present?в RoR тоже хорошо.
Tokland

это действительно ломается в Ruby 2.4 с помощью Path! [43] (pry) # <ReactOnRails :: AssetsPrecompile>: 0> assets_path.blank? true [44] (pry) # <ReactOnRails :: AssetsPrecompile>: 0> Путь к ресурсам.to_s "/ var / folder / rp / _k99k0pn0rsb4d3lm9l3dnjh0000gn / T / d20170603-96466-zk7di7" [45] (pry) # <ReactOncompails >: 0> Assets_path.present? false [46] (pry) # <ReactOnRails :: AssetsPrecompile>: 0> assets_path.nil? false
justingordon 04

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 нет? в Ruby. Но если это не будет , !self.nil?а потом !nil?, или selfнеявный?
Berkes

3
Вам не нужно «я». Это будет подразумеваться.
Geo,

Я подразумевается при чтении из методов экземпляра (или средств доступа, которые на самом деле являются просто методами). При установке значений переменная, локальная для метода, будет создана до того, как Ruby проверит экземпляр класса на предмет одноименного метода установки. Общее правило: если у вас есть attr_accessor с именем xxx, используйте «self.xxx = 3» (установка значения) или «temp = xxx» (чтение значения). Использование «xxx = 3» не обновит метод доступа, просто создаст новую переменную в области действия метода.
A 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?
berkes

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