39

我认为这样做只是常识和 Ruby 约定,但我有这种方法:

def is_subscribed?(feed_url)
  Subscription.find_by_user_id_and_feed_id(self[ :id ], Feed.find_by_feed_url(feed_url))
end

我得到的唯一困惑是,这不会像我最初预期的那样返回布尔值,方法是将问号放在方法名称的末尾。我的印象是,当评估一个有条件的对象时,它会返回trueif not nil

显然我在这里忽略了这一点,它没有像我想的那样评估它。

所以,我的问题是,最好只做一个if (condition) true else false?还是有更优雅的方法来做到这一点?

4

6 回答 6

44

以 ? 结尾的方法 应该返回一个可以评估为真或假的值。如果要确保返回布尔值,可以通过在查找器中添加双键来实现。

def is_subscribed?(feed_url)
  !!Subscription.find_by_user_id_and_feed_id(self[ :id ], Feed.find_by_feed_url(feed_url))
end
于 2012-05-10T05:30:53.263 回答
22

在方法名称的末尾添加 a?不会以任何方式改变方法的返回值,而只是表明它是一个谓词方法。也就是说,方法的返回值应该被视为布尔值,但不需要是严格的布尔值(即truefalse)。

许多其他答案表明它应该返回一个真值或假值。这是相当多余的,因为一切都可以是真或假,而且由于 Ruby 中的所有方法都返回一些东西(除非它们引发异常),所以返回值总是真或假。

将 a 附加为其他语言中附加?的更好的替代方案;is_例如,我要么有subscribed?要么is_subscribed

于 2012-05-10T05:46:14.017 回答
5

它应该是一个 'truthy' 或 'falsy' 值,可以在谓词中安全使用,但不必返回文字truefalse. File.size?标准库中甚至还有这样的方法,例如。

于 2012-05-10T05:31:06.147 回答
2

实际上,具体来说——以问号结尾的方法应该返回可以被测试为trueor的值false

rails 中有很多方法可以从 '?' 返回非布尔值。方法。

事实上,最近有一个 pull request 提交给 rails 项目,它把注意力集中在这个确切的问题上:

https://github.com/rails/rails/pull/5582

基本上,讨论是围绕这个确切的问题进行的——方法只需要返回可以测试为真或假的值,如下所示:

if (condition)
  # do 'truthy option
else
  # do non-truthy option
end

从这个角度来看,我相信你的方法很好。

于 2012-05-10T05:31:22.413 回答
1

其他答案很好地涵盖了返回值。

我将补充一点,现代风格指南不鼓励is_布尔方法的前缀。尾随的问号涵盖了该语义糖。

来自https://github.com/rubocop-hq/ruby-style-guide

布尔方法问号

谓词方法(返回布尔值的方法)的名称应以问号结尾(即 Array#empty?)。不返回布尔值的方法不应以问号结尾。

布尔方法前缀

避免在谓词方法前加上 is、does 或 can 等助动词。这些话是多余的,不符合Ruby核心库中布尔方法的风格,比如empty? 并包括?

于 2019-11-06T15:30:14.120 回答
0

另一种选择是使用三元/条件运算符来强制布尔返回。

 if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this

我同意其他人将您的方法名称更改为

 def subscribed? 
于 2020-07-23T01:08:22.530 回答