在Ruby中,有些方法带有问号(?),会问include?询问是否包含有问题的对象,然后返回true/false。

但是为什么有些方法有感叹号(!)而其他方法没有呢?

这是什么意思?


当前回答

底线:!方法只改变被调用对象的值,而没有!返回一个被操纵的值,而不重写调用该方法的对象。

只用!如果您不打算将原始值存储在调用方法的变量中。

我喜欢这样做:

foo = "word"
bar = foo.capitalize
puts bar

OR

foo = "word"
puts foo.capitalize

而不是

foo = "word"
foo.capitalize!
puts foo

以防万一我想再次访问原始值。

其他回答

这个命名约定来自Scheme。

1.3.5命名约定 按照惯例,程序的名称 总是返回一个布尔值 通常以“?”结尾。这样的程序 称为谓词。 按照惯例,程序的名称 存储值到先前 已分配的位置(见3.4节) 通常以“!”结尾。这样的程序 叫做变异程序。通过 方法返回的值 突变过程未指明。

它是最准确的说,方法与Bang!是更危险或更令人惊讶的版本。有很多方法在没有Bang的情况下会发生突变,比如.destroy,通常情况下,方法只有Bang,而核心库中存在更安全的替代方法。

例如,在Array中,我们有.compact和.compact!,这两个方法都会改变数组,但是.compact!如果数组中没有nil则返回nil而不是self,这比只返回self更令人惊讶。

我发现唯一的非突变方法是Kernel的.exit!这比.exit更令人惊讶,因为你无法在进程关闭时捕获SystemExit。

Rails和ActiveRecord延续了这一趋势,因为它使用bang来实现更多“令人惊讶”的效果,如.create!这会在失败时产生错误。

底线:!方法只改变被调用对象的值,而没有!返回一个被操纵的值,而不重写调用该方法的对象。

只用!如果您不打算将原始值存储在调用方法的变量中。

我喜欢这样做:

foo = "word"
bar = foo.capitalize
puts bar

OR

foo = "word"
puts foo.capitalize

而不是

foo = "word"
foo.capitalize!
puts foo

以防万一我想再次访问原始值。

!

我喜欢把这看作是一个爆炸性的变化,它摧毁了之前的一切。Bang或感叹号表示您正在对代码进行永久保存的更改。

如果你使用Ruby的方法进行全局替换,sub!你所做的替换是永久的。

你可以想象的另一种方式是,打开一个文本文件,进行查找和替换,然后保存。! 在代码中执行相同的操作。

如果您来自bash世界,另一个有用的提醒是sed -i具有永久保存更改的类似效果。

我的回答解释了在Ruby on Rails (RoR)模型验证上下文中带有感叹号/shebangs的Ruby方法的重要性。

本质上,无论何时开发人员定义模型验证(此处解释),他们的最终目标都是拒绝数据库记录更改,并在提交了无效数据以更新相关记录的情况下引发/抛出相关异常。

RoR ActiveRecord gem定义了各种模型操作方法(Ruby on Rails指南)。在这些方法中,有效的?方法是唯一一个无需数据库操作/修改就能触发验证的方法。其余的方法尝试更改数据库。

这些方法在运行时触发回调。列表中的一些方法有一个带shebang的姐妹方法。这两者之间有什么区别?它与记录验证失败时返回的回调形式有关。

不带感叹号/shebang的方法在记录验证失败时只返回布尔值false,而带shebang的方法会引发/抛出异常,然后可以在代码中适当地处理。