{"record":{"id":"d3645b56d764bddf","repo":"paper-trail-gem/paper_trail","slug":"passing-versions-association-name-as-has-paper-tr","errorCode":null,"errorMessage":"Passing versions association name as `has_paper_trail versions: %{versions_name}` is deprecated. Use `has_paper_trail versions: {name: %{versions_name}}` instead. The hash you pass to `versions:` is now passed directly to `has_many`.","messagePattern":"Passing versions association name as `has_paper_trail versions: %(.+?)` is deprecated\\. Use `has_paper_trail versions: (.+?)\\}` instead\\. The hash you pass to `versions:` is now passed directly to `has_many`\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"lib/paper_trail/model_config.rb","lineNumber":195,"sourceCode":"\n    def define_has_many_versions(options)\n      options = ensure_versions_option_is_hash(options)\n      check_version_class_name(options)\n      check_versions_association_name(options)\n      scope = get_versions_scope(options)\n      @model_class.has_many(\n        @model_class.versions_association_name,\n        scope,\n        class_name: @model_class.version_class_name,\n        as: :item,\n        **options[:versions].except(:name, :scope)\n      )\n    end\n\n    def ensure_versions_option_is_hash(options)\n      unless options[:versions].is_a?(Hash)\n        if options[:versions]\n          PaperTrail.deprecator.warn(\n            format(\n              DPR_PASSING_ASSOC_NAME_DIRECTLY_TO_VERSIONS_OPTION,\n              versions_name: options[:versions].inspect\n            ),\n            caller(1)\n          )\n        end\n        options[:versions] = {\n          name: options[:versions]\n        }\n      end\n      options\n    end\n\n    # Process an `ignore`, `skip`, or `only` option.\n    def event_attribute_option(option_name)\n      [@model_class.paper_trail_options[option_name]].\n        flatten.","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/paper-trail-gem/paper_trail/blob/098058ae472d13763fe66e6866a6a4dfc64a3eca/lib/paper_trail/model_config.rb#L177-L213","documentation":"has_paper_trail's `versions:` option used to accept a bare symbol/string naming the versions association (`versions: :audit_records`). ensure_versions_option_is_hash in lib/paper_trail/model_config.rb:195 now requires a Hash — the hash is forwarded directly to `has_many` (see the setup at model_config.rb:186-192, which splats `options[:versions].except(:name, :scope)`), so :name and :scope moved inside it. A non-nil non-Hash value triggers this deprecation via PaperTrail.deprecator and is then coerced to `{ name: options[:versions] }`, so current behavior is preserved but the bare form will stop working in a future release.","triggerScenarios":"Writing `has_paper_trail versions: :my_versions` or `versions: \"my_versions\"` (any truthy non-Hash) in a model on paper_trail 11+/12+. Fires at boot when ModelConfig#ensure_versions_option_is_hash runs; `versions: nil`, `versions: false`, or an omitted key do NOT warn (the `if options[:versions]` guard).","commonSituations":"Models upgraded from paper_trail < 11 that renamed the association via the old `versions: :symbol` shorthand; developers mixing the two syntaxes (`versions: { name: :x }` in one model, `versions: :x` in another); code generators or templates still emitting the pre-11 form.","solutions":["Convert the bare value to a hash with the :name key: `has_paper_trail versions: { name: :audit_records }`.","If you also customize the association scope or other has_many options, put them in the same hash (`versions: { name: :audit_records, scope: -> { order(\"created_at DESC\") } }`) since the hash now goes directly to has_many.","Sweep the codebase for other models using the shorthand and set `PaperTrail.deprecator.behavior = :raise` in tests so remaining call sites fail CI."],"exampleFix":"# app/models/article.rb - before\nhas_paper_trail versions: :article_versions\n\n# app/models/article.rb - after\nhas_paper_trail versions: { name: :article_versions }","handlingStrategy":"validation","validationCode":"# CI guard: fail if any model passes a bare symbol/string to versions:\n# grep -rn --include='*.rb' -E 'has_paper_trail[^\\n]*versions:\\s*:[a-zA-Z_]' app lib && exit 1 || exit 0","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass `versions:` as a Hash: `{ name: ... }` for the association name, and any other has_many options alongside it.","Remember `versions: nil` / `versions: false` do NOT warn (falsy values skip the check), so only truthy bare values are a smell — but be explicit anyway.","Enable `PaperTrail.deprecator.behavior = :raise` in the test environment so shorthand usage from generators or older models breaks CI immediately."],"tags":["ruby","paper-trail","deprecation","activerecord","association-name"],"backgroundTag":"deprecated-option-migration","analyzedSha":"098058ae472d13763fe66e6866a6a4dfc64a3eca","analyzedAt":"2026-08-21T18:44:58.137Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}