我正面临着一种非常奇怪的行为.这是Ruby 2.6.6,因此循环中的块散列变量不会被冻结.在本例中,source处于冻结状态.

执行此操作:

result = source.tap { |s| s.delete(:key) }

带回一张不带:key键的source.

从理论上讲,这一点也是如此:

result = source.except(:key)

还有这一点:

result = source.dup.tap { |s| s.delete(:key) }

据我所知,上述三种句法的结果是相同的.

然而,在测试(Ruby 2.6.6,Rails 6.0.6.1)中,使用第一种语法的规范成功,而使用后两种语法的规范失败.我不知道是否有必要说明到底是哪一项测试,我只是在寻找一个解释.

对于为什么会发生这种情况,有什么建议吗?

先谢谢你.

推荐答案

Summary

选项1使用Object#tap.Object#tap:

将self返回给块,然后返回self.此方法的主要目的是"利用"方法链,以便对链中的中间结果执行操作.

这不会创建"副本",因此使用Hash#delete可以就地修改source.

选项2和选项3确实创建了一个浅层副本.

这意味着如果#1在您的测试中有效,而#2和#3在测试中不起作用,那么可以合理地假设您测试的是source而不是result.

TL;DR

让我们对以下语句进行判断:"Brings back a copy of the 100 without the 101 key."

为简洁起见,我们将使用source = {key: 10}

示例和解释:

  • 示例1:result = source.tap { |s| s.delete(:key) }

    • "Brings back a copy of the 100 without the 101 key."-假.如果不使用:key键,则返回source.
result = source.tap { |s| s.delete(:key) }
#= > {} 
result == source 
#=> true
source
# {}
  • 例2:result = source.except(:key)

    • "Brings back a copy of the 100 without the 101 key."-True(在Rails>;3.0和Ruby>;2.7中)
result = source.except(:key)
#=> {} 
result == source 
#=> false
source
# {key: 10}
  • 例3:result = source.dup.tap { |s| s.delete(:key) }

    • "Brings back a copy of the 100 without the 101 key."--正确
result = source.dup.tap { |s| s.delete(:key) }
#=> {} 
result == source 
#=> false
source
# {key: 10}

Ruby-on-rails相关问答推荐

ActiveAdmin:的呈现索引表在父级的显示页中有许多资源

线程如何在 Web 应用程序中工作?

从 rails 5 迁移到 rails 6

Selenium chromedriver:无法从不可键入的键构造KeyEvent

如何避免 activesupport 中的循环参数引用警告

设计 token_authenticable 已弃用,有什么替代方案?

键入rails 控制台无法启动?

Rails 3 - Select 包含?

rails4 未知编码名称 - CP720

从 Rails 生成 PDF

将 cookie 会话存储添加回 Rails API 应用程序

Rails Mailer Net::OpenTimeout: execution expired 仅在生产服务器上出现异常

form_tag 是否与 Simple_form 一起使用?

在 Ruby on Rails 中循环对象属性

从 Rails 中的控制器调用辅助方法时出现未定义的方法

Rails,Docker:主机不存在:默认

设计:为什么我的注销链接不起作用?

Ruby/Rails CSV 解析,UTF-8 中的无效字节序列

在 Rails 4.1 中,如何通过枚举符号查找记录?

如何创建一个 ruby​​ Hello 世界?