我正在努力让计数器缓存在 has_one :through 上工作,但遇到了一些奇怪的行为。我想在模型上有一个 counter_cache ,用于缓存关联(通过模型)Company
的数量。Location
BusinessUnit
对象:
class Company < ApplicationRecord
has_many :business_units, class_name: :BusinessUnit, dependent: :destroy
has_many :locations, through: :business_units, dependent: :destroy, counter_cache: :locations_count
end
class BusinessUnit < ApplicationRecord
belongs_to :company, counter_cache: :locations_count
has_many :locations, dependent: :destroy
end
class Location < ApplicationRecord
belongs_to :business_unit
has_one :company, through: :business_unit
end
架构:
ActiveRecord::Schema[7.1].define(version: 2025_04_03_203549) do
enable_extension "plpgsql"
create_table "business_units", force: :cascade do |t|
t.string "name"
t.bigint "company_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["company_id"], name: "index_business_units_on_company_id"
end
create_table "companies", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "locations_count", default: 0, null: false
end
create_table "locations", force: :cascade do |t|
t.string "name"
t.bigint "business_unit_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["business_unit_id"], name: "index_locations_on_business_unit_id"
end
add_foreign_key "business_units", "companies"
add_foreign_key "locations", "business_units"
end
根据这些 SO 答案 ( 1、2 ),我的理解是这应该可行。关于 Rails 如何自动知道引用位置计数,文档并不完善,而且有点违反直觉,但实际上它似乎确实有一些 Rails 魔力,Company.reset_counters(1, :locations)
正确调用会将计数器设置为匹配位置数。
但是,当添加或删除位置时,计数器不会自动更新(增加或减少),并且如果更新具有 N 个位置的业务单元并将其分配给另一家公司,则计数器只会增加/减少 1(而不是预期的 N 个位置)。此行为在 Rails 8.0.1 和 7.1.3(我无意中用它们来构建我的 MRE)中都存在。
我是否遗漏了一些明显可以使 counter_cache 正常工作的东西?