Ruby nil.to_s in Ruby 2.7.0 now always return a frozen String

Peter · 2020年03月21日 · 最后由 Peter 回复于 2020年03月21日 · 3412 次阅读

https://www.ruby-lang.org/en/news/2019/12/25/ruby-2-7-0-released/

Module#name, true.to_s, false.to_s, and nil.to_s now always return a frozen String.

使用的一个 Gem 里面莫名其妙地抛出一个 FrozenError

FrozenError in XxxxxController#action
can't modify frozen String: ""

本地调试了好久才找到关键行:

foo = bar.to_s
foo.gsub!(/正则/,"")

bartrue, falsenil 的时候,foo 就自动 frozen 了,再 gsub! 的时候就报 FrozenError

加个判断就可以 fix 了:

foo.gsub!(/正则/,"") unless foo.frozen?

也可以 duplicate 一下,但这应该会多创建一个 object,浪费资源,降低执行速度

foo = bar.to_s.dup

比较奇怪的是,这个 Gem 在 Linux 服务器上的 Ruby 2.7.0 并不报错,只在本地 macOS 10.14 上报错。

irb(main):001:0> true.to_s.gsub!(/正则/,"")
...
FrozenError (can't modify frozen String: "true")

这就怪了,我两个环境都试过,ruby2.7.0 都会报这个错。🤐 确定这个 Gem 在 Linux 上所依赖的环境也是 2.7.0 吗?

lanzhiheng 回复

我在 Linux 上试了也会报错,可能是我只用 cap production puma:restart 重启了一下,Rails 可能还在用老版本的 ruby 及 Gems。等下次部署的时候再观察一下以。

$ rbenv versions
  2.5.1
* 2.7.0 (set by /home/deploy/.rbenv/version)
需要 登录 后方可回复, 如果你还没有账号请 注册新账号