Compare commits

...

2 Commits

Author SHA1 Message Date
Dylan Knutson
fb7912e353 spec for habtm counter cache 2025-07-21 16:58:58 +00:00
Dylan Knutson
025cbd3f5c more tests for join counter caches 2025-07-21 16:45:50 +00:00
4 changed files with 61 additions and 43 deletions

View File

@@ -67,7 +67,6 @@ module HasAuxTable
setup_initialize_hook!(config)
setup_changed_hook!(config)
setup_save_hook!(config)
setup_reload_hook!(config)
setup_attributes_hook!(config)
setup_relation_extensions!(config)
setup_attribute_getter_setter_hooks!(config)
@@ -328,38 +327,6 @@ module HasAuxTable
end
end
sig { params(config: AuxTableConfig).void }
def setup_reload_hook!(config)
refresh_object =
lambda do |target, fresh|
target.instance_variable_set(
:@association_cache,
fresh.instance_variable_get(:@association_cache)
)
target
.instance_variable_get(:@association_cache)
.each_value { |association| association.owner = target }
target.instance_variable_set(
:@attributes,
fresh.instance_variable_get(:@attributes)
)
end
self.define_method(:reload) do |*args|
T.bind(self, ActiveRecord::Base)
aux_model = config.aux_model_for(self)
fresh_object = self.class.find(id)
refresh_object.call(self, fresh_object)
refresh_object.call(
aux_model,
fresh_object.association(config.aux_association_name).target
)
self
end
end
sig { params(config: AuxTableConfig).void }
def setup_attributes_hook!(config)
attributes_method = self.instance_method(:attributes)

View File

@@ -192,7 +192,6 @@ module HasAuxTable
aux_model = config.aux_model_for(self)
ret =
T.unsafe(aux_model).public_send(method_name, *args, **kwargs, &block)
puts "#{self.class.name}##{method_name} -> #{config.aux_association_name} -> (#{args.inspect} => #{ret})"
ret
end
end

View File

@@ -758,15 +758,6 @@ RSpec.describe HasAuxTable do
d = drivers.find_by(license_number: 123_456)
expect(d.id).to eq(driver.id)
end
# it "can create STI models through associations" do
# user =
# TwitterUser.create!(last_login_at: Time.now, twitter_handle: "a_user")
# post = user.posts.create!(title: "twitter post")
# expect(post.user).to eq(user)
# expect(post.user_id).to eq(user.id)
# expect(post.user.twitter_handle).to eq("a_user")
# end
end
describe "#reload" do
@@ -953,6 +944,32 @@ RSpec.describe HasAuxTable do
verify_counter_cache(a, :model_cs, i + 1)
end
end
it "is a join table connecting two base classes" do
a = ModelA.create!(a_field1: "a1_0")
ds = 5.times.map { ModelD.create! }
verify_counter_cache(a, :ad_joins, nil)
ds.each { |d| verify_counter_cache(d, :ad_joins, nil) }
ds.each_with_index do |d, i|
a.ad_joins.create!(model_d: d)
verify_counter_cache(a, :ad_joins, i + 1)
verify_counter_cache(d, :ad_joins, 1)
end
end
it "is a join table connecting two subclasses" do
a = ModelA1.create!(a_field1: "a1_0", a1_field1: "a1_0")
ds = 3.times.map { |i| ModelD1.create!(d1_field1: "d1_#{i}") }
verify_counter_cache(a, :ad_joins, nil)
ds.each { |d| verify_counter_cache(d, :ad_joins, nil) }
ds.each_with_index do |d, i|
a.ad_joins.create!(model_d: d)
verify_counter_cache(a, :ad_joins, i + 1)
verify_counter_cache(d, :ad_joins, 1)
end
end
end
describe "joins model with aux tables" do

View File

@@ -288,6 +288,7 @@ ActiveRecord::Schema.define do
create_base_table :model_as do |t|
t.string :a_field1
t.integer :model_bs_count
t.integer :ad_joins_count
t.create_aux :a1 do |t|
t.integer :a1_field1
@@ -326,15 +327,33 @@ ActiveRecord::Schema.define do
}
end
create_base_table :model_ds do |t|
t.integer :ad_joins_count
t.create_aux :d1 do |t|
t.string :d1_field1
end
end
create_table :ad_joins, primary_key: %i[model_a_id model_d_id] do |t|
t.references :model_a, foreign_key: { to_table: :model_as }
t.references :model_d, foreign_key: { to_table: :model_ds }
end
# A* has_many B
# A1 has_many C
# A* has_many ADJoin
# B belongs_to A
# C belongs_to A1
# D* has_many ADJoin
# ADJoin belongs_to A
# ADJoin belongs_to D
end
class ModelA < ActiveRecord::Base
include HasAuxTable
has_many :model_bs, inverse_of: :model_a
has_many :ad_joins, inverse_of: :model_a
has_many :model_ds, through: :ad_joins
validates :a_field1, presence: true, uniqueness: true
end
@@ -370,3 +389,19 @@ class ModelC < ActiveRecord::Base
belongs_to :model_a1, inverse_of: :model_cs, counter_cache: true
validates :c_field1, presence: true, uniqueness: true
end
class ModelD < ActiveRecord::Base
include HasAuxTable
has_many :ad_joins, inverse_of: :model_d
has_many :model_as, through: :ad_joins
end
class ModelD1 < ModelD
aux_table :d1
validates :d1_field1, presence: true, uniqueness: true
end
class AdJoin < ActiveRecord::Base
belongs_to :model_a, inverse_of: :ad_joins, counter_cache: true
belongs_to :model_d, inverse_of: :ad_joins, counter_cache: true
end