Ruby
Rails
MongoDB
mongoid

mongo-ruby-driverを2.5.0にあげたらサーバー接続エラーが出る

経緯

MongoDBを使っているRailsアプリで、Rubyのバージョンを上げようとした時の話。
バージョン2.4以前のmongo gemを使っていて、Rubyのバージョンを2.4以上に上げようとすると以下のような警告が大量に出る。

/.../.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/mongo-2.4.3/lib/mongo/cursor.rb:225: warning: Mongo::Cursor#limit at /.../.rbenv/versions/2.5.0/lib/ruby/2.5.0/forwardable.rb:157 forwarding to private method Mongo::Index::View#limit

実はこの対策はすでに取られていて、mongo gemの2.5に入れられている。
https://jira.mongodb.org/browse/RUBY-1240

そこでbundle update mongoを行って2.4.3->2.5.0に更新したのだが、railsを起動したところ

Mongo::Error::NoServerAvailable: No server is available matching preference: #<Mongo::ServerSelector::Primary:0x70282203496220 tag_sets=[] max_staleness=nil> using server_selection_timeout=30 and local_threshold=0.015

というエラーが出て接続できなくなってしまった。

原因と対策

変更したのはmongo gemのバージョンだけだったので、ソースの差分を確認してみた。
https://github.com/mongodb/mongo-ruby-driver/compare/v2.4.3...v2.5.0

すると怪しい箇所を発見

lib/mongo/address.rb
-          res = FAMILY_MAP[info[4]].new(info[3], port, host)
+          res = FAMILY_MAP[info[4]].new(host, port, host)

おそらく、この変更によってアドレス解決に失敗するようになったのだろう。ちょっとgemを編集してinfohostを出力してみる。

info => ["AF_INET", 0, "127.0.0.1", "127.0.0.1", 2, 1, 6]
host => "localhost"

というわけで原因がわかった。hostにはrailsアプリのconfig/mongoid.ymlで設定している値が入っているので、このファイル内でIPアドレスで指定するようにした。

config/mongoid.yml
       hosts:
-        - localhost:27017
+        - 127.0.0.1:27017

これによって無事にmongo gemを更新することができた。