paper-trail-gem/paper_trail · warning
Passing Version class name as `has_paper_trail class_name: %
Error message
Passing Version class name as `has_paper_trail class_name: %{class_name}` is deprecated. Use `has_paper_trail versions: {class_name: %{class_name}}` instead. The hash you pass to `versions:` is now passed directly to `has_many`. What it means
has_paper_trail's old `class_name:` option (used to point a host model at a custom Version class) was replaced by the `versions:` hash. check_version_class_name in lib/paper_trail/model_config.rb:159 detects `options[:class_name]`, warns via PaperTrail.deprecator, then copies the value into `options[:versions][:class_name]` so behavior is unchanged for now. The `versions:` hash is now passed straight to `has_many`, so the old flat key will be removed in a future PT release — code relying on it will then silently fall back to PaperTrail::Version or raise.
Source
Thrown at lib/paper_trail/model_config.rb:159
def assert_valid_recording_order_for_on_destroy(recording_order)
unless %w[after before].include?(recording_order.to_s)
raise ArgumentError, 'recording order can only be "after" or "before"'
end
if recording_order.to_s == "after" && cannot_record_after_destroy?
raise Error, E_CANNOT_RECORD_AFTER_DESTROY
end
end
def cannot_record_after_destroy?
::ActiveRecord::Base.belongs_to_required_by_default
end
def check_version_class_name(options)
# @api private - `version_class_name`
@model_class.class_attribute :version_class_name
if options[:class_name]
PaperTrail.deprecator.warn(
format(
DPR_CLASS_NAME_OPTION,
class_name: options[:class_name].inspect
),
caller(1)
)
options[:versions][:class_name] = options[:class_name]
end
@model_class.version_class_name = options[:versions][:class_name] || "PaperTrail::Version"
assert_concrete_activerecord_class(@model_class.version_class_name)
end
def check_versions_association_name(options)
# @api private - versions_association_name
@model_class.class_attribute :versions_association_name
@model_class.versions_association_name = options[:versions][:name] || :versions
end
View on GitHub (pinned to 098058ae47)
Solutions
- Replace the flat option with the nested hash: `has_paper_trail versions: { class_name: "MyVersion" }`.
- If you were only passing class_name to get the default, drop the option entirely — PT defaults to PaperTrail::Version.
- Make deprecations loud in test/CI (`PaperTrail.deprecator.behavior = :raise`) and fix every call site before the next PT major, where the legacy key is removed.
Example fix
# app/models/article.rb - before
has_paper_trail class_name: "ArticleVersion"
# app/models/article.rb - after
has_paper_trail versions: { class_name: "ArticleVersion" } Defensive patterns
Strategy: validation
Validate before calling
# CI guard: fail if any model still uses the deprecated flat option # (run from repo root; adjust dirs to your layout) # grep -rn --include='*.rb' -E 'has_paper_trail[^\n]*class_name:' app lib | grep -v 'versions:' && exit 1 || exit 0
Prevention
- Adopt the `versions: { ... }` hash form in all new code; it is forwarded verbatim to has_many, so any has_many option you need goes there.
- Run tests with `PaperTrail.deprecator.behavior = :raise` so any remaining deprecated call site fails fast at boot.
- After upgrading paper_trail majors, grep app/models for `has_paper_trail` and diff each option list against the current README before shipping.
When it happens
Trigger: Declaring a host model with `has_paper_trail class_name: "MyVersion"` (or passing `class_name:` inside has_paper_trail options in any form) on paper_trail 11+/12+. Fires once per model class at boot time when ModelConfig#check_version_class_name runs, with caller(1) pointing at the offending model file.
Common situations: Apps upgrading from paper_trail < 11 (where `class_name:` was the documented syntax for Custom Version Classes) to PT 11/12+; old initializers or gems that configure `has_paper_trail class_name:` on behalf of models; copy-pasted blog examples predating the option reshuffle.
Related errors
- Passing versions association name as `has_paper_trail versio
- PaperTrail %s is not compatible with ActiveRecord %s. We all
- Attribute #{k} does not exist on #{version.item_type} (Versi
AI-assisted analysis of paper-trail-gem/paper_trail@098058ae47 (2026-08-21).
Data as JSON: /api/errors/ca733439045409ce.
Report an issue: GitHub.