From bddd0b145dbb96dbddd10ed51a13d08ff39c4f89 Mon Sep 17 00:00:00 2001 From: Todd Sedano Date: Mon, 29 Apr 2024 08:02:06 -0700 Subject: [PATCH] Fixes Rails 7.1 raise_on_assign_to_attr_readonly --- CHANGELOG.md | 5 +++- lib/paper_trail/reifier.rb | 2 +- spec/dummy_app/app/models/wotsit.rb | 1 + spec/models/wotsit_spec.rb | 39 ++++++++++++++++++++++++----- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f177347b..b232263b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,10 @@ recommendations of [keepachangelog.com](http://keepachangelog.com/). ### Fixed -- None +- [#1467](https://github.com/paper-trail-gem/paper_trail/issues/1467) - Rails 7.1 + enables ActiveRecord.raise_on_assign_to_attr_readonly so that writing to a + attr_readonly raises an exception. Fixes paper trail to gracefully handle this + situation. ### Dependencies diff --git a/lib/paper_trail/reifier.rb b/lib/paper_trail/reifier.rb index d78f8720..f2484579 100644 --- a/lib/paper_trail/reifier.rb +++ b/lib/paper_trail/reifier.rb @@ -92,7 +92,7 @@ def init_unversioned_attrs(attrs, model) # @api private def reify_attribute(k, v, model, version) if model.has_attribute?(k) - model[k.to_sym] = v + model[k.to_sym] = v unless model.class.readonly_attribute?(k.to_s) elsif model.respond_to?("#{k}=") model.send("#{k}=", v) elsif version.logger diff --git a/spec/dummy_app/app/models/wotsit.rb b/spec/dummy_app/app/models/wotsit.rb index 37445535..f048ef00 100644 --- a/spec/dummy_app/app/models/wotsit.rb +++ b/spec/dummy_app/app/models/wotsit.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true class Wotsit < ApplicationRecord + attr_readonly :id has_paper_trail belongs_to :widget, optional: true diff --git a/spec/models/wotsit_spec.rb b/spec/models/wotsit_spec.rb index e72fbefa..5ed930af 100644 --- a/spec/models/wotsit_spec.rb +++ b/spec/models/wotsit_spec.rb @@ -3,12 +3,39 @@ require "spec_helper" RSpec.describe Wotsit, versioning: true do - it "update! records timestamps" do - wotsit = described_class.create!(name: "wotsit") - wotsit.update!(name: "changed") - reified = wotsit.versions.last.reify - expect(reified.created_at).not_to(be_nil) - expect(reified.updated_at).not_to(be_nil) + context "when handling attr_readonly attributes" do + context "without raise_on_assign_to_attr_readonly" do + before do + # Rails 7.1 first introduces this setting, and framework_defaults 7.0 has it as false + if ActiveRecord.respond_to?(:raise_on_assign_to_attr_readonly) + ActiveRecord.raise_on_assign_to_attr_readonly = false + end + end + + it "update! records timestamps" do + wotsit = described_class.create!(name: "wotsit") + wotsit.update!(name: "changed") + reified = wotsit.versions.last.reify + expect(reified.created_at).not_to(be_nil) + expect(reified.updated_at).not_to(be_nil) + end + end + + if ActiveRecord.respond_to?(:raise_on_assign_to_attr_readonly) + context "with raise_on_assign_to_attr_readonly enabled" do + before do + ActiveRecord.raise_on_assign_to_attr_readonly = true + end + + it "update! records timestamps" do + wotsit = described_class.create!(name: "wotsit") + wotsit.update!(name: "changed") + reified = wotsit.versions.last.reify + expect(reified.created_at).not_to(be_nil) + expect(reified.updated_at).not_to(be_nil) + end + end + end end it "update! does not raise error" do