是否有Ruby或Ruby-ism的not_nil?与零相反?方法?


87

我没有使用Ruby的经验,所以我的代码感觉“丑陋”且不习惯:

def logged_in?
  !user.nil?
end

我宁愿有类似的东西

def logged_in?
  user.not_nil?
end

但是找不到相反的方法 nil?

Answers:


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 2011年

9
当心2:我还要注意!! user不能区分用户为nil和用户为false。Double-bang用法将这两者混为一谈。因此,如果您确实要确定某个对象是否不是nil(意味着,它是:true,false,0,“”,除nil以外的其他值),则需要使用berkes不喜欢的“丑陋”方法或@Tempus在下面建议的猴子补丁。当然在这种情况下不是nil时的需要(在滑轨的用户),通过萨莫采取的方法是最难看,伊莫。
likethesky 2013年

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

3
这个答案根本不能回答所问的问题。这是对特定实现问题的解答。
Ekkstein '16

3
这个答案是不正确的。假。是false,而false.present?也是假的!
迈克(Mike)

49

您似乎过于关心布尔值。

def logged_in?
  user
end

如果用户为零,那么login_in?将返回“假”值。否则,它将返回一个对象。在Ruby中,我们不需要返回true或false,因为我们具有JavaScript中的“ truthy”和“ falsey”值。

更新资料

如果您使用的是Rails,可以使用以下present?方法使此内容更好看:

def logged_in?
  user.present?
end

1
以a结尾的方法的期望?是返回一个布尔值。!!value是将任何内容转换为布尔值的经典方法。不完全一样,但是在这种情况下Object#present?,RoR也不错。
tokland

这实际上在Ruby 2.4中用Path破坏了![43](尝试)#<ReactOnRails :: AssetsPrecompile>:0> asset_path.blank?true [44](尝试)#<ReactOnRails :: AssetsPrecompile>:0> asset_path.to_s“ / var / folders / rp / _k99k0pn0rsb4d3lm9l3dnjh0000gn / T / d20170603-96466-zk7di7” [45](尝试)#<ReactOnPreils:As >:0> asset_path.present?假[46](尝试)#<ReactOnRails :: AssetsPrecompile>:0> asset_path.nil?错误
justingordon

25

当心其他答案present?作为您的问题的答案。

present?blank?in rails相反。

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。还有什么:一个空字符串,0false,什么,是不是nil

present?是非常有用的,但绝对不是相反的nil?。混淆两者可能导致意外错误。

对于您的用例来说present?,它是可行的,但是了解它们之间的差异总是明智的。


应该包含在接受的答案中。false.blank?false.nil?
Yason

present?将查询您的数据库,nil?不会,请小心
Tony

17

也许这是一种方法:

class Object
  def not_nil?
    !nil?
  end
end

好主意。我由此得出结论,没有not_nil吗?在Ruby中。但是如果不是这种!self.nil?而不是!nil?,或者是self隐含的?

3
你不需要自我。这将被暗示。
地理

从实例方法(或访问器,实际上只是方法)读取时,隐含了self。设置值时,将在Ruby检查类实例的同名setter方法之前创建该方法本地的变量。一般规则:如果您有一个名为xxx的attr_accessor,请使用“ self.xxx = 3”(设置值)或“ temp = xxx”(读取值)。使用“ xxx = 3”将不会更新访问器,仅在方法范围内创建一个新变量。
黑暗的推子

4

您可以使用以下命令:

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

这不仅适用于nil,而且适用于false等,因此您应该进行测试,看看它是否在用例中有效。


4

我可以在!方法结果上提供Ruby-esquenil?方法。

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
伊恩
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.