@ledsun blog

無味の味は佳境に入らざればすなわち知れず

SQLite3でridgepoleを動かす

GitHub - ridgepole/ridgepole: Ridgepole is a tool to manage DB schema. It defines DB schema using Rails DSL, and updates DB schema according to DSL. (like Chef/Puppet) はSQLite3をサポートしていません。

READMEに0.6.0以降 Disable sqlite support と明記されています。 まあ、でもRails 8以降SQLiteが推されてますし、SQLite3にも使いたいじゃないですか。 今日は、雑にどんな修正が必要そうか考えてみます。

対応するオプション

SQLite3はadd_column メソッドのうち次のオプションが使えません。

  • after
  • null

他にもあるかもしれません。 今回はこの対応だけを考えます。

準備

SQLite3で分岐するために https://github.com/ridgepole/ridgepole/blob/ff299198a20fbfdc51e8779bb790c923cb98dd8c/lib/ridgepole/connection_adapters.rb にSQLite3判定メソッドを追加します。

module Ridgepole
  class ConnectionAdapters
    def self.mysql?
      defined?(ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter) && ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter)
    end

    def self.postgresql?
      defined?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) && ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
    end

    def self.sqlite3?
      defined?(ActiveRecord::ConnectionAdapters::SQLite3Adapter) && ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)
    end
  end
end

afterオプション

https://github.com/ridgepole/ridgepole/blob/ff299198a20fbfdc51e8779bb790c923cb98dd8c/lib/ridgepole/diff.rb#L274-L278afterオプションを追加しています。 まるごと除外します。

unless Ridgepole::ConnectionAdapters.sqlite3?
  if priv_column_name
    to_attrs[:options][:after] = priv_column_name
  else
    to_attrs[:options][:first] = true
  end
end

null オプション

https://github.com/ridgepole/ridgepole/blob/ff299198a20fbfdc51e8779bb790c923cb98dd8c/lib/ridgepole/dsl_parser/table_definition.rb#L96 でSchemefileのカラム定義に書いてあるオプションをを読み込んでいます。 ここでnullオプションを無視します。

define_method column_type do |*args|
  options = args.extract_options!
  if Ridgepole::ConnectionAdapters.sqlite3?
    options.delete(:null)
  end

  options = default_options.merge(options)
  column_names = args

  column_names.each { |name| column(name, column_type, options) }
end

修正案を書きましたが、そもそもSchemefileにnullオプションを書かない方が良さそうに思います。

まとめ

とりあえずSQLite3でもridgepoleは使えます。

メンテナンスする自信が無いのに、サポート範囲を広げるを投げるのは、メンテナの負荷を増やしすぎる問題があります。 しばらく手元で動かしてみて、他に問題が出ないか試してみます。

2025/11/16 追記

SQLiteは非null制約をサポートしています。 マイグレートに失敗したのは、既にnullが入っている行があったからでした。 勘違いしていました。