SQLite on Railsシリーズ(03)SQLite拡張機能を読み込む(翻訳)
今回もRuby on Railsアプリケーションを強化するためにSQLiteを強化します。本記事では、SQLiteデータベースに拡張機能を読み込む方法について詳しく説明します。
個人的には、基本的にSQLiteの機能は完全であると思っていますが、SQLiteでサポートされていない特定のデータベースニーズが生じる場合もあります。ありがたいことに、SQLiteは豊富な拡張機能エコシステムを提供しています。パッケージマネージャ(非公式)---sqlpkg
、標準ライブラリ(非公式)---sqlean
、およびAlex Garciaによるさまざまな拡張機能の豊富なコレクションが揃っています。SQLite 拡張機能のインストールに関する一般的な概要については以下の記事をどうぞ。
参考: How to install an SQLite extension
しかし私たちが欲しいのは、RailsアプリケーションにSQLite拡張機能を手軽にインストールして読み込める方法です。残念ながら、現時点のsqlpkg
やsqlean
の拡張機能コレクションはRuby gemリリースを提供していません。
しかしありがたいことに、Alex Garciaは各拡張機能をRuby gemとしてリリースしています。Alexの拡張機能はすべてRubyGemsのプロファイルで見つけられます。これらの拡張機能の1つをインストールして読み込む手軽な方法を見ていくことにしましょう。
これらはRuby gemなので、インストールは簡単です。bundle add 拡張機能名
を実行するだけです。読み込みはもっと込み入っています。
拡張機能を読み込む前に、まずSQLiteデータベースの拡張機能読み込みを有効にしておく必要があります。Ruby用のsqlite3-ruby
アダプタは、そのための#enable_load_extension
メソッドを提供します。
Alex Garciaの拡張機能では、拡張機能を読み込むRuby拡張機能クラスに.load
メソッドを提供します。したがって、RubyでSQLiteの拡張機能を読み込むには、次の操作をすべて実行する必要があります。
@raw_connection.enable_load_extension(true)
SqliteExtension.load(@raw_connection)
@raw_connection.enable_load_extension(false)
ただし、開発エクスペリエンスを損なわない形でRailsを強化したいと思います。では、この機能をエレガントに公開するにはどうすればよいでしょうか?ありがたいことに、前回の記事で/config/database.yml
ファイルに設定されたオプションを使ってデータベースを設定するためのフックを提供するSQLite3
アダプタの機能強化を既に導入してあります。
拡張機能名の配列を受け取るextensions
セクションのサポートも追加できます。次に、これらの拡張機能名を反復処理して読み込むように以下のようにconfigure_connection
メソッドに追加できます。
module RailsExt
module SQLite3Adapter
def configure_connection
# ...
@raw_connection.enable_load_extension(true)
@config[:extensions].each do |extension_name|
require extension_name
extension_classname = extension_name.camelize
extension_class = extension_classname.constantize
extension_class.load(@raw_connection)
rescue LoadError
Rails.logger.error("Failed to find the SQLite extension gem: #{extension_name}. Skipping...")
rescue NameError
Rails.logger.error("Failed to find the SQLite extension class: #{extension_classname}. Skipping...")
end
@raw_connection.enable_load_extension(false)
end
end
end
bundle add {拡張機能名}
コマンドを実行したら、/config/database.yml
ファイルのextensions
セクションに拡張機能を追加すればおしまいです。
RailsExt::SQLite3Adapter
が残りの処理を行い、起こりうるエラーにも対処します。つまり、次のようなdefault
セクションを作成することで、ULIDをサポートするために拡張機能を読み込めます。
default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
# BUSY例外をスローする直前にコネクションを試行する
retries: 1000
extensions:
- sqlite_ulid
この方法でSQLite拡張機能を読み込む場合の嬉しい点は、拡張機能が(Gemfile
で)明示的にインストールされることと、拡張子が(database.yml
ファイル内で)明示的に読み込まれることと、SQLiteアダプタの既存の拡張機能の上に自然に構築されることです。全体として、拡張されたアダプターは プラグマ構成と拡張機能の読み込みをサポートするようになりました。
さらに、データベース設定のおかげでGitブランチを切り替えるとデータベースも切り替わる方法が強化されます。
これにより、ローカル開発を強力にする豊富な機能セットが提供されます。
次回の記事では、Litestream
をインストールして設定し、productionデータベースでポイントインタイムのバックアップとリカバリーを実現する方法について詳しく説明します。どうぞお楽しみに。
原注
本記事で行った最終的な実装についてはGistで参照できます。
概要
原著者の許諾を得て翻訳・公開いたします。
参考: Rails 8はSQLiteで大幅に強化された「個人が扱えるフレームワーク」(翻訳)|YassLab 株式会社
日本語タイトルは内容に即したものにしました。