Chienomi

サイト小改修……からのRubyのバージョンアップで一苦労

開発::website

  • TOP
  • Articles
  • 開発
  • サイト小改修……からのRubyのバージョンアップで一苦労

Harukamy’s ChatshowHarukamy Piecesを少し改修した。

最も大きいのは、両者ともPlusOneを追加したこと。 高評価は、特にそれに伴う効果はなくてもモチベーション的には大事なので、Chatshow以外のサイトにも配置するようにしてきている。

余談だが、PlusOneはもともと👍️+1という表示であったが、これは当時流行っていたSNS(Twitter, Facebook, Google+)の間を取った感じだったのだが、+1表記が消えたのもひとつのアップデート。 ただし、機能名称自体はPlusOneのままである。

PlusOneや検索などの機能は、基本的にBasic WebAppsというアプリケーションにまとめられており、設定ファイルによってサイトが定義される形になっている。 このため、PlusOneを採用するサイトを増やすのは難しくない。

またもうひとつ大きな変更として、ShareToSNSのサービス名をTwitterからXに変更した。 ただ、これは正直微妙だ。 Xはあまりにもブランド名やブランドカラーを軽視しており、とにかく「伝わらない」。 名称はXに変更したが、帯色についてはXのもの(#0F1419)ではなくTwitterのもの(#1DA1F2)を継続採用している。 その理由はもちろん、Xの色を採用してもそのボタンが「Xへのシェアを意味する」と認識されないからだ。

これらはあまり大きな変更ではない。 PlusOneに関してはJavaScriptを使っているが、基本的にPlusOneのコードは大部分が流用可能なものである。また、Scriptがなくても動作はする。スクリプトはあくまで表示変更のためのものだからだ。

だがこの変更の直前に行ったアップデートにより、Rubyが3.2から3.3に上がったことで思わぬ問題が生じた。 ちなみに、Archlinuxは長い間(OoDになった)3.0を使っており、放置された状態にあったが、最近(なぜか最新の3.3ではなく)3.2にアップデートされ、そこからほどなく3.3に上がった形である。

RubyGemsの基本

RubyGemsはRubyの公式のライブラリ管理システムである。 Rubyの場合はシステムワイド、またはユーザーワイドでライブラリを導入するほうが基本。

Node.jsのnode_modulesのようにプロジェクトに閉じたライブラリ管理としてはbundlerというものがある。

そして、インストールされているGemsはRuby自体のバージョン固有になっている。

例えばArchlinuxのシステムであれば、Ruby 3.3.xのシステムワイドのGemsは/usr/lib/ruby/gems/3.3.0に、ユーザーのGemsは~/.local/share/gem/ruby/3.3.0に保存される。

このため、Rubyのバージョンが変わるとインストールされたすべてのGemsを見失う。

また、Rubyの場合はBundled Gemsになったことにより明示的な指定が必要になったり、標準添付ライブラリから削除されたりといったことが起きる。 3.0以降にあった変更は:

3.3
  • readline (削除)
  • racc (bundled gems)
3.1
  • net-ftp (bundled gems)
  • net-imap (bundled gems)
  • net-pop (bundled gems)
  • net-smtp (bundled gems)
  • matrix (bundled gems)
  • prime (bundled gems)
  • debug (bundled gems)
3.0
  • sdbm (削除)
  • webrick (削除)
  • net-telnet (削除)
  • xmlrpc (削除)
  • rexml (bundled gems)
  • rss (bundled gems)

という感じ。

このため、単純に前バージョンでインストールされていたGemsをインストールすればいいかというとそうでもない。

今回起きた問題

ライブラリの欠乏

3.2から3.3に上がったことに最初気づかなかったので、当然ながらGemsがインストールされていないことによるエラーでアプリが落ちていた。

このチェックは結構大変。 bundlerを使っているならbundle installすれば良いのだが、ライブラリ削除とかがあると結局ひっかかる。

比較的良いチェック方法として、

script_dirs=(/path/to/a /path/to/b)

for i in $script_dirs
do
  (
    cd $i
    grep "^require " **/*.rb~vendor/*
  )
done > dependency.rb

とかして標準ライブラリも含めてrequireだけするものを作って実行すれば欠如しているライブラリが分かる。

が、私の場合ローカルなライブラリを$:で追加していたりするため、この方法もあんまりうまくいかない。

ThinとRack

私のウェブアプリはSinatraを使っているのだが、Sinatra, Rack, Rackup, RackHandler周りはバージョン齟齬によって地獄を見ることがめちゃくちゃ多い。 以前CGIHandlerを使っていた状態からThinに切り替えるときもかなり苦労した。

今回はThinのハンドラがないと言われて「????」になっていた。

例えばこのようなコード

#!/bin/ruby
require 'sinatra/base'

class App < Sinatra::Base
  SOCKET_PATH = "./test.sock"
  set , "thin"
  set , SOCKET_PATH
end

App.run!

.../ruby/3.3.0/gems/rackup-2.1.0/lib/rackup/handler.rb:81:in `pick': Couldn't find handler for: thin. (LoadError)
        from .../ruby/3.3.0/gems/sinatra-4.0.0/lib/sinatra/base.rb:1624:in `run!'
        from thinsinatra.rb:11:in `<main>'

となる。

「確かにThinは入ってるし、ThinのRackハンドラはあるのに……」となってしまうのだが、この問題はThinがRack3に対応していない、ということに由来する。

Sinatraは以前はサーバーとしてThinをドキュメントに書いていたのだが、いつの間にかPumaに変わっている。

私はThinかPumaかに強いこだわりがあるわけではないため、今回はPumaに乗り換えることにした。 ちなみに、RubyのwebアプリケーションサーバーでアクティブなプロジェクトはPumaとThinしかなさそうで、Rackupが標準で同梱するのはCGIとWebrickだけになっている。 ここらへんの事情も結構厳しい。 FastCGIもなくなったん……

先のコードは単純に

#!/bin/ruby
require 'sinatra/base'

class App < Sinatra::Base
  SOCKET_PATH = "./test.sock"
  set , "puma"
  set , SOCKET_PATH
end

App.run!

とするだけでPumaを使うようになる。 もちろん、ライブラリのインストールをお忘れなく。

Bundleのほうがいいか?

空気的にはgemよりbundleするほうが流行りなのかなぁとは感じる。 多分、人々がwebに毒されすぎてるせいだと思うのだけど。

個人的にはシステムで/usr/local/bin~/.local/bin以下において使っているプログラムをRubyで書いていることが多いため、bundleを使っていこうという気持ちはそんなにない。というか、プログラムの数が多いのでそれをやっているとめちゃくちゃめんどくさいことになる。

なのでどちらかといえば「全部requireしてテストしてみる」方式のほうが現実的だ。

ちなみに、bundleの手順としては

  • bundle init する
  • bundle config set path 'vendor/bundle' する
  • Gemfile に必要なgemを記載する
  • スクリプトの冒頭で require 'bundler/setup' する
  • 動かす環境で bundle installする

って感じ。 全体がひとつのwebアプリケーションみたいなケースはこの方法のほうが簡単。

Rubyの欠点

Rubyの良いところは書きやすく、強力なライブラリが標準添付されていることだが、Rubyの明確な欠点はライブラリがちゃんと保守されていないケースが多すぎることだ。

多くの人が利用しているライブラリでもそのまま放置されるなんてことはザラにあり、他の言語と比べてもライブラリに頼らないほうが良い度合いが強い。

そしてRubyはこれまで添付されていたライブラリが消えるということがあるのもつらい。 とにかくライブラリ周りには苦しめられる言語だ。

ただまぁ、保守に伴うアプデで苦しまない言語を私は知らない1ので、受け入れるべきなのだろうけども。