Ruby 3.3リリース! 新機能解説

徹底解説! default gemsとbundled gemsのすべて

この記事では、毎年少しずつ変化している標準添付ライブラリ、Default gemsとBundled gemsのRuby 3.3でのアップデートについて解説します。

標準添付ライブラリとDefault gems/Bundled gems⁠それぞれの違い

私、柴田はRubyインタプリタと同時に配布されている便利なライブラリ群(標準添付ライブラリ)の開発だけではなく、アップデートや配布の仕組みを担当しています。この標準添付ライブラリの中にはDefault gemsとBundled gems、そしてどちらでもないライブラリの3種類があります。便宜上ではありますが、どちらでもないライブラリのことを標準ライブラリと呼ぶことにし、それぞれの特徴について解説します。

標準ライブラリ

標準ライブラリは、RipperやCoverageなど、Rubyのインタプリタの挙動に深く依存するライブラリです。標準ライブラリはgemとして配布したとしても、動かすことができるRubyのバージョンがRubyのminorバージョンと同一になってしまいます。つまり、Ruby 3.2.0で動く標準ライブラリは、Ruby 3.2.1などでは動かすことができても、Ruby 3.1やRuby 3.3では同じバージョンであったとしても、異なる挙動であったり動かない、ということです。

後述するDefault gemsやBundled gemsという概念の導入前はすべての標準添付ライブラリが、Rubyのバージョンとともに更新されるという状態でした。この状態はRipperなどのようにRubyインタプリタと密結合している標準ライブラリにとってはわかりやすいですが、ライブラリにセキュリティアップデートが必要とされるような脆弱性が見つかった場合にRubyインタプリタも含めた新しいバージョンのリリースが必要となります。

また、標準ライブラリはRubyインタプリタのインストール先と同じディレクトリの下に配置され、そのディレクトリは$LOAD_PATHに追加されるため、RubyGemsやBundlerの環境下であってもrequireによって呼び出すことができます。

Default gems

Default gemsは標準添付ライブラリのうち、Rubyインタプリタに依存しないライブラリ(前述した標準ライブラリ)をgemとしても配布したものです。Default gemsは標準ライブラリと異なり、Rubyインタプリタのバージョンとは独立してアップデートやリリースがなされるため、セキュリティアップデートが必要となった場合でも、ユーザーはRubyインタプリタを変更することなくgem updatebundle updateでバージョンをアップデートすることができます。

Default gemsは標準ライブラリをgemとして配布したもののため、標準ライブラリ同様にRubyGemsやBundlerの環境下であっても、requireによって呼び出すことができます。また、セキュリティアップデートや、新機能をいち早く使いたい場合などにRubyGemsのgemメソッドやBundlerのGemfileを用いることで任意のバージョンを呼び出すことも可能です。

Bundled gems

Bundled gemsはDefault gemsの中から、Rubyコミッタによる開発を卒業して、Rubyコミッタ以外の開発者がリリースまで含めたメンテナンスを行うようになったgemです。中には最初からgemとしてリリースされたもののうち、Rubyのリリースバージョンとともに動くことが保証された上で一緒にインストールされたほうが良いと判断されたものが、Bundled gemsとして含まれることもあります。

Bundled gemsはRailsなど通常のgemに以下の項目を与えたものになります。

  • Rubyインタプリタと共にインストールされる。Rubyインタプリタがサポートしているプラットフォームでビルド・インストールできることが保証されている
  • Rubyインタプリタの開発と共にテストが行われている。Rubyのリリースバージョンで動くことが保証されている

gemのインストールや動作確認は時にして期待通りにならないことが多く、上記の2項目だけでも利用者にとっては大きいメリットと思います。また、Bundled gemsは標準ライブラリやDefault gemsとは異なり、通常のgemのインストールと同様に扱われるため、ユーザーが任意にアンインストールすることもできます。そして、Bundlerの環境下で利用する場合はGemfileに明示的に記述する必要があります。

注目すべきRuby 3.3での標準添付ライブラリのアップデート

Ruby 3.3では標準添付ライブラリのうち、Default gems 2つについて、注意すべき変更があります。それぞれの変更について解説します。

readline-extが削除された

Ruby 3.2まではCで書かれたreadline-extと呼ばれるlibreadlineの機能を扱えるようにするラッパーライブラリと、Rubyで書かれたlibreadlineの互換ライブラリであるreline、そしてreadline-extrelineを切り替えるためのライブラリであるreadlineの3つがDefault gemsとして添付されていました。

Ruby 3.3ではrelineが実用上問題ないレベルでreadline-extの代わりとして利用できると判断し、readline-extが削除されました。この変更により、require "readline"を実行するとrelineが呼び出されるようになります。従来のreadline-extを利用したい場合はgem install readline-extでインストールするか、BundlerのGemfilegem "readline-ext"と記述することで利用できます。

実用上問題ないレベルとはいえ、まだまだrelineにはreadline-extとは異なる挙動が残っています。発見した場合はrelineのリポジトリのIssueに報告していただけると幸いです。

raccがBundled gemsになった

raccはRubyとCで書かれたLALR(1)パーサジェネレータです。Ruby 3.2まではDefault gemsとして添付されていましたが、多くのgemですでに依存関係として追加されていることから、Default gemsとしての役割を終えたと判断し、Ruby 3.3ではBundled gemsになりました。

この変更により、Ruby 3.3ではraccを使う際には、BundlerのGemfilegem "racc"と明示的に記述する必要があります。

Bundled gemsの警告機能の追加

私はRubyのリポジトリのみに存在していたライブラリについて、Default gemsに変更し、さらにBundled gemsに変更するという活動を通して、新しいメンテナを見つけてRubyのライブラリの持続的な開発が行えるようになることを目指しています。しかし、前の節で紹介したように、Default gemsからBundled gemsにすることで利用者からみると対象のライブラリを Gemfileに追加するという作業を必要とします。

そこで、Ruby 3.3ではRuby 3.4でDefault gemsからBundled gemsにする予定のライブラリを利用する際に、利用者に対して警告を出す機能が追加されました。

Bundled gemsの利用時に警告が出るケース

警告の対象となるライブラリはRuby 3.3.0 Releasedに記載されていますが、以下のライブラリです。

  • abbrev
  • base64
  • bigdecimal
  • csv
  • drb
  • getoptlong
  • mutex_m
  • nkf
  • observer
  • resolv-replace
  • rinda
  • syslog

以降は具体的な挙動について解説を行います。

この警告機能はBundlerの環境下でのみ有効となります。そのため、テストコードではGemfileではなく、bundler/inlineを用いていますが、gemfileブロックの中はGemfileに記載されているものと読み替えてください。

require "bundler/inline"

gemfile do
  source "https://rubygems.org"
end

require "mutex_m"
require "rss"

上記のコードをRuby 3.3で実行すると以下のような出力が得られます。

$ ruby test_warn_bundled_gems.rb
test_warn_bundled_gems.rb:7: warning: mutex_m was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add mutex_m to your Gemfile or gemspec.
test_warn_bundled_gems.rb:8: warning: rss was loaded from the standard library, but is not part of the default gems since Ruby 3.0.0. Add rss to your Gemfile or gemspec.
/Users/hsbt/.local/share/rbenv/versions/3.3.0-dev/lib/ruby/3.3.0/bundled_gems.rb:74:in `require': cannot load such file -- rss (LoadError)

この警告はmutex_mライブラリはRuby 3.4でBundled gemsになること、rssライブラリはRuby 3.0でBundled gemsになったことを伝えています。そのため、これらのライブラリを利用する場合はGemfileに明示的に記述する必要があります。

require "bundler/inline"

gemfile do
  source "https://rubygems.org"
  gem "mutex_m"
  gem "rss"
end

require "mutex_m"
require "rss"

最初のコードのgemfileブロックにgem "mutex_m"gem "rss"を追加することで、警告が出なくなります。

$ ruby test_warn_bundled_gems.rb
# 何も出力されない

ライブラリ開発者向けの警告

また、この警告は、ライブラリの中で使われている場合にも出力されます。たとえばRails 7.0.7.2では、bigdecimalなどは依存ライブラリとして追加されていません。そのため、Ruby 3.3で以下のようなコードを実行するとbigdecimalなどに関する警告がでます。

require "bundler/inline"

gemfile do
  source "https://rubygems.org"
  gem "activesupport", "7.0.7.2"
end

require "active_support/all"

実行結果は以下のとおりです。

$ ruby test_warn_dependency.rb
/Users/hsbt/.local/share/gem/gems/activesupport-7.0.7.2/lib/active_support/core_ext/big_decimal/conversions.rb:3: warning: bigdecimal was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add bigdecimal to your Gemfile or gemspec. Also contact author of activesupport-7.0.7.2 to add bigdecimal into its gemspec.
/Users/hsbt/.local/share/gem/gems/activesupport-7.0.7.2/lib/active_support/notifications/fanout.rb:3: warning: mutex_m was loaded from the standard library, but will no longer be part of the default gems since Ruby 3.4.0. Add mutex_m to your Gemfile or gemspec. Also contact author of activesupport-7.0.7.2 to add mutex_m into its gemspec.

最初の例と同様に、bigdecimalとmutex_mの2つのライブラリについて、Ruby 3.4でBundled gemsになることを伝えています。また、⁠Also contact author of activesupport-7.0.7.2 to add bigdecimal into its gemspec.⁠という警告が追加されています。これはactivesupportがbigdecimalを利用しているため、activesupportのgemspecに依存ライブラリとしてbigdecimalを追加してくださいという警告です。

自分のコードでbigdecimalを使ってる場合には、Gemfileなどに追加するだけで解決できますが、根本的な解決としてはactivesupportが依存関係としてbigdecimalを追加する必要があります。なお、2024年1月29日時点ではRails 7.1.0ではすでに対応済み、Rails 7.0では7.0-stableブランチでは対応済みなので、7.0.9がリリースされた場合、bigdecimalなどの依存関係の問題は解決されています。このように、将来Bundled gemsになる予定のDefault gemsについては、手元のコードはもちろんのこと、利用しているライブラリがBundled gemsの候補ライブラリである場合は、まず開発が行われているGitHubリポジトリ等で修正が行われているかを確認し、未修正の場合はライブラリの開発者に依存関係を追加するように連絡してもらえるとありがたいです。

まとめとRuby 3.4に向けて

この記事では、Ruby 3.3で変更のあった、Default gems 2つについてと、Ruby 3.4でDefault gemsからBundled gemsになる予定のライブラリを利用する際に出力される警告機能について紹介しました。今回紹介した機能が将来リリースされるRubyを使った際に予期せぬエラーを回避できるような事前の備えの助けになれば幸いです。

Ruby 3.4以降は引き続きDefault gemsをBundled gems 、またはBundled gemsを卒業して通常のgemへ変更していくことを通して、Ruby コミッタだけではなくより多くの人がRubyの開発に参加できるようになることを目指しています。ご興味のある方はruby-jpのslackなどでお声がけください。

おすすめ記事

記事・ニュース一覧