Railsのエラー『ArgumentError: AfterCommit callback can only be defined on the root class』の解決方法

Railsのモデルにafter_commitコールバックを定義する際に発生する「ArgumentError: AfterCommit callback can only be defined on the root class」エラーの原因と対策について説明します。このエラーは、継承関係のあるモデルで発生することが多く、適切な修正を行うことで解決できます。
目次
エラーの発生条件
このエラーは、STI(Single Table Inheritance)を使用したモデルのサブクラスでafter_commit
を定義しようとした場合に発生します。たとえば、以下のようなコードが原因になります。
class Parent < ApplicationRecord
end
class Child < Parent
after_commit :some_method
def some_method
puts "After commit callback executed"
end
end
Railsは、after_commitコールバックをルートクラス(最上位の親クラス)で定義することを前提としているため、サブクラスで定義するとエラーになります。
エラーメッセージの例
ArgumentError: AfterCommit callback can only be defined on the root class (Parent)
解決策1: ルートクラスで定義する
after_commitをSTIの親クラスで定義することでエラーを回避できます。
class Parent < ApplicationRecord
after_commit :some_method
def some_method
puts "After commit callback executed"
end
end
class Child < Parent
end
解決策2: コールバックを個別に適用
サブクラスごとに異なる処理をしたい場合は、カスタムメソッド内で処理を分岐させることができます。
class Parent < ApplicationRecord
after_commit :common_after_commit
private
def common_after_commit
if self.is_a?(Child)
puts "Child-specific after_commit"
else
puts "Parent-specific after_commit"
end
end
end
解決策3: ActiveSupport::Concernを使用
モジュールを作成し、STIのサブクラスで適用する方法もあります。
module AfterCommitHandler
extend ActiveSupport::Concern
included do
after_commit :some_method
end
def some_method
puts "After commit callback executed"
end
end
class Parent < ApplicationRecord
end
class Child < Parent
include AfterCommitHandler
end
解決策4: コールバックの代わりにActiveJobを使用
コールバックを使用せず、非同期処理として実行する方法も有効です。
class SomeJob < ApplicationJob
queue_as :default
def perform(record_id)
record = Parent.find(record_id)
puts "After commit logic executed for #{record.id}"
end
end
class Parent < ApplicationRecord
after_commit -> { SomeJob.perform_later(self.id) }
end
まとめ
- after_commitはSTIのルートクラスで定義する
- サブクラスごとの処理を分岐させる場合はメソッド内で条件分岐
- ActiveSupport::Concernを活用してモジュールとして適用する
- コールバックの代わりにActiveJobを使用する方法も考慮する
これらの方法を活用することで、「ArgumentError: AfterCommit callback can only be defined on the root class」エラーを回避し、適切にafter_commitを活用できます。
-
前の記事
PHPのエラー『Notice: compact(): Undefined variable found』の解決方法 2025.05.18
-
次の記事
Railsのエラー『RuntimeError: Circular dependency detected while autoloading constant』の解決方法 2025.05.19
コメントを書く