ActiveRecord::Base.establish_connection 周りのエラーと対策の備忘録

2021年にruby2.5がEOLになったのでツールをメンテすることに

  • 安定していた2.5系が2021年4月5日でEOLに
  • rbenvで2.6系, 2.7系, 3.0系をインストールして動作確認をする

備忘録として注意点や具体的な対策等をブログに残します。

2.6,2.7よりも3.0系以上の方がいいらしい

理由は後述するが、バグや脆弱性対策を考慮すると2.6,2.7系よりも3.0以降を利用したほうが良い。
但し、3.0以降は破壊的変更が多数あるので、gemの依存関係で動かない場合は2.7系の最新版を使った方が良い場合もある。
今回はRuby 3.0.3を利用して Gemfile のうち以下つをバージョン指定にすると正常にインストールができた。

  • Gemfileの例(Ruby 3.0.3利用)
    gem 'psych', '~> 4.0'
    gem 'bigdecimal', '1.4.2'
    gem 'psych', '~> 4.0'
    gem 'mysql2', '~>0.4.9'
    

上のgem以外は個別にバージョン指定が必要なコンポーネントを調べて、
"gem update”でバージョンに合致するgemにアップデートすればいい。

YAML周りの謎のエラー

  • YAML.load_fileが非推奨化で、なぜかYAML.unsafe_loadが代替

  • YAML.unsafe_loadだとデータが空っぽで読み込まれる

  • エラーが意味不明

    undefined method `[]' for nil:NilClass (NoMethodError)
    

    上記は、YAML.unsafe_loadでデータを読み込んだけど中身が空っぽだったので接続情報(establish_connection)に渡した内容(Class)もNilになっているという意味らしい。

  • YAML周りのエラーと仕様変更について

    • YAML.load_file(Psych.load)の処理ではRCEの脆弱性が含まれていて、既存の仕様では対策ができないので廃止になったらしい
    • RCE脆弱性といえばlog4jで大騒ぎになったアレだが、RubyのYAML周りの処理もclass変換される仕様なので、yml処理がハックされると同様の危険性がある
    • 脆弱性に対応した YAML.load_file が提供される予定は今のところ発表されていない
      YAML|Deserialization on Rails

これまでYAML.load_fileで対処できていたDBの初期化は、自前でyamlなりjsonを読み込んで実装する必要がある。

ActiveRecord::Migration 周りでエラーが発生した場合

Rails5以降にアップデートしてMigrationしたコードの場合は自動生成されるのだが、
単体でActiverecordを利用している場合は、Migrationメソッドにバージョン番号を付与しなければならない仕様が追加されている。

  • 旧来のMigrationコード

    class CreateRssTable < ActiveRecord::Migration
    
  • Rails5以降のMigrationコード

    class CreateRssTable < ActiveRecord::Migration[7.0]
    

手っ取り早くMySQL周りを動作確認する

  • 旧来の接続処理を外す

単体でactiverecordを使う場合は、以下のような初期化処理を使うことが多いと思うのだが、
旧来の処理はコメントアウトする。

#config = YAML.load_file('./database.yml')
#ActiveRecord::Base.establish_connection(config["db"]["development"])

代わりに以下のようにestablish_connectionへ接続情報を付与する。
ハードコードになってしまうが、動作確認して問題がなければ、外部読込みに置換えればいい。

ActiveRecord::Base.establish_connection(
:adapter => "mysql2",
:host => "localhost",
:database => "db_name",
:user => "db_user",
:password => "db_password"
)

対策した感想

脆弱性の背景を知れば「仕方がない」とも思えるが、
YAML.load_fileのような基本的な処理が突然使えなくなると「Rubyを使うのをやめよう」と思う人も多いような気がする。
自分もあまりRubyを使わなくなってしまったが、日本製のプログラム言語として頑張ってほしい。