From ea33ffbb11b14989fa2ca0eae69c18a4cea2266d Mon Sep 17 00:00:00 2001 From: Dylan Knutson Date: Fri, 18 Jul 2025 17:49:26 +0000 Subject: [PATCH] changed, changed_attributes --- lib/has_aux_table.rb | 19 +++++++++++ spec/active_record/has_aux_table_spec.rb | 41 ++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/lib/has_aux_table.rb b/lib/has_aux_table.rb index d73085e..8dfc956 100644 --- a/lib/has_aux_table.rb +++ b/lib/has_aux_table.rb @@ -51,6 +51,7 @@ module HasAuxTable setup_attribute_types_hook!(config) setup_load_schema_hook!(config) setup_initialize_hook!(config) + setup_changed_hook!(config) setup_save_hook!(config) setup_reload_hook!(config) setup_attributes_hook!(config) @@ -266,6 +267,24 @@ module HasAuxTable end end + sig { params(config: AuxTableConfig).void } + def setup_changed_hook!(config) + changed_method = self.instance_method(:changed?) + self.define_method(:changed?) do + T.bind(self, ActiveRecord::Base) + changed_method.bind(self).call || config.aux_model_for(self).changed? + end + + changed_attributes_method = self.instance_method(:changed_attributes) + self.define_method(:changed_attributes) do + T.bind(self, ActiveRecord::Base) + changed_attributes_method + .bind(self) + .call + .merge(config.aux_model_for(self).changed_attributes) + end + end + sig { params(config: AuxTableConfig).void } def setup_save_hook!(config) %i[save save!].each do |method_name| diff --git a/spec/active_record/has_aux_table_spec.rb b/spec/active_record/has_aux_table_spec.rb index 865e525..c30bbfb 100644 --- a/spec/active_record/has_aux_table_spec.rb +++ b/spec/active_record/has_aux_table_spec.rb @@ -99,6 +99,47 @@ RSpec.describe HasAuxTable do expect(lot.vehicles.first.name).to eq("vehicle1") end + describe "#changed?" do + it "returns true if the main record changes" do + car = Car.create!(name: "Honda Civic") + expect(car.changed?).to be_falsey + car.name = "Toyota Camry" + expect(car.changed?).to be_truthy + end + + it "returns true if the aux record changes" do + car = Car.create!(name: "Honda Civic") + expect(car.changed?).to be_falsey + car.fuel_type = "hybrid" + expect(car.changed?).to be_truthy + end + end + + describe "#changed_attributes" do + # changed_attributes returns a hash with the original values of the attribute + + it "returns the changed attributes of the main record" do + car = Car.create!(name: "Honda Civic") + expect(car.changed_attributes).to eq({}) + car.name = "Toyota Camry" + expect(car.changed_attributes).to eq({ "name" => "Honda Civic" }) + end + + it "returns the changed attributes of the aux record when original is nil" do + car = Car.create!(name: "Honda Civic") + expect(car.changed_attributes).to eq({}) + car.fuel_type = "hybrid" + expect(car.changed_attributes).to eq({ "fuel_type" => nil }) + end + + it "returns the changed attributes of the aux record when original is not nil" do + car = Car.create!(name: "Honda Civic", fuel_type: "gasoline") + expect(car.changed_attributes).to eq({}) + car.fuel_type = "hybrid" + expect(car.changed_attributes).to eq({ "fuel_type" => "gasoline" }) + end + end + describe "database integration" do it "provides automatic attribute accessors for auxiliary table columns" do vehicle = Car.create!(name: "Honda Civic")