为什么在Rails中不能使用Record.all.destroy?

7

我目前正在学习Ruby和Ruby on Rails框架。我发现在表格records中,我可以使用以下代码找到id为5的记录并删除它:

Record.find(5).destroy

这很容易理解- 我将方法链接在一起以查找并销毁该记录。但是,如果我想要销毁表格中的所有记录,则逻辑命令应为以下内容,因为all选择器会选择表格中的所有记录:

Record.all.destroy

然而,这会返回NoMethodError错误!我知道我可以使用Record.destroy_allRecord.delete_all来完成这个任务,但是,我想知道为什么我不能只使用最符合逻辑的选择,而不必查找像delete_all这样的东西。我对这个框架还很陌生,所以完全有可能我在这里忽略了某些基本事项。

提前感谢任何回答。


确实是一个好问题,因为我也尝试过同样的事情... 当然,你可以使用 Record.all.each { |r| r.destroy },但这不如 Record.all.destroy 逻辑清晰。 - Simon Woker
5个回答

14

这是一个设计决策。DataMapper采用了你的方式。强制显式地编写destroy_all可能会很繁琐,但也能防止你做出不想要的事情(例如删除表中的所有内容,比如x = User; ...; x.destroy)。


谢谢 - 这就是我正在寻找的答案。我猜这可能是防止意外删除记录的很好保护。 - element119

3

我同意这样做是合理的。技术上讲,Record.all 返回一个集合(或集合代理),它没有实现 destroy 方法。


1

当你拥有

Record.find(5)

这将返回一个代表表格中一行数据的Record对象/实例。然后,您可以在该对象上调用#destroy方法,该方法由您的Record模型定义。

当您拥有

Record.all

这将返回一个数组对象。为了能够在数组上调用 #destroy 方法,您需要对 Ruby 的核心 Array 类进行猴子补丁。


是的和不是的...由于Ruby的动态特性,Rails本身可以在记录数组上插入销毁操作,而无需猴子补丁所有数组对象...但我认为这是一个设计决策。 - DGM

1
避免使用 Record.destroy_all 最简单的方法是使用 Record.all.each {|r| r.destroy}。这种方法可能会满足您的 API 设计偏好,但速度比第一种选项慢得多。

0

实际上你可以(以某种方式)。由于.all返回的是一个数组,而不是一个活动记录关系,那么你到底要删除什么?我不认为Record.all.destroy有任何逻辑--你是在删除数组对象吗?

你可以做的一件事是映射结果数组,由于map接受一个proc(&),你可以为数组中的每个对象执行该proc。

Record.all.map(&:destroy)

请注意,这将触发所有对象的回调,可能比您预期的要慢。如果您想避免触发回调,可以映射适当的破坏性方法而不是销毁方法。(提示::delete)
或者,您也可以只执行以下操作:
Record.destroy_all or Record.delete_all

正如您在问题中所述。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接