diff --git a/app/controllers/api/v1_alpha/collections_controller.rb b/app/controllers/api/v1_alpha/collections_controller.rb index 65c08d8d6b..d0c4e0f3f0 100644 --- a/app/controllers/api/v1_alpha/collections_controller.rb +++ b/app/controllers/api/v1_alpha/collections_controller.rb @@ -71,7 +71,6 @@ class Api::V1Alpha::CollectionsController < Api::BaseController def set_collections @collections = @account.collections .with_tag - .with_item_count .order(created_at: :desc) .offset(offset_param) .limit(limit_param(DEFAULT_COLLECTIONS_LIMIT)) diff --git a/app/models/collection.rb b/app/models/collection.rb index 231f12ef52..2e352cbe87 100644 --- a/app/models/collection.rb +++ b/app/models/collection.rb @@ -7,6 +7,7 @@ # id :bigint(8) not null, primary key # description :text not null # discoverable :boolean not null +# item_count :integer default(0), not null # local :boolean not null # name :string not null # original_number_of_items :integer @@ -39,11 +40,6 @@ class Collection < ApplicationRecord validate :items_do_not_exceed_limit scope :with_items, -> { includes(:collection_items).merge(CollectionItem.with_accounts) } - scope :with_item_count, lambda { - select('collections.*, COUNT(collection_items.id)') - .left_joins(:collection_items) - .group(collections: :id) - } scope :with_tag, -> { includes(:tag) } def remote? diff --git a/app/models/collection_item.rb b/app/models/collection_item.rb index 48a18592fd..093005fd3e 100644 --- a/app/models/collection_item.rb +++ b/app/models/collection_item.rb @@ -17,7 +17,7 @@ # collection_id :bigint(8) not null # class CollectionItem < ApplicationRecord - belongs_to :collection + belongs_to :collection, counter_cache: :item_count belongs_to :account, optional: true enum :state, diff --git a/app/serializers/rest/base_collection_serializer.rb b/app/serializers/rest/base_collection_serializer.rb index 0e9bfc4cfc..be26aac6fe 100644 --- a/app/serializers/rest/base_collection_serializer.rb +++ b/app/serializers/rest/base_collection_serializer.rb @@ -9,8 +9,4 @@ class REST::BaseCollectionSerializer < ActiveModel::Serializer def id object.id.to_s end - - def item_count - object.respond_to?(:item_count) ? object.item_count : object.collection_items.count - end end diff --git a/db/migrate/20251209093813_add_item_count_to_collections.rb b/db/migrate/20251209093813_add_item_count_to_collections.rb new file mode 100644 index 0000000000..071cfab46a --- /dev/null +++ b/db/migrate/20251209093813_add_item_count_to_collections.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddItemCountToCollections < ActiveRecord::Migration[8.0] + def change + add_column :collections, :item_count, :integer, default: 0, null: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 4e8a9f6efb..51595381f5 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2025_12_02_140424) do +ActiveRecord::Schema[8.0].define(version: 2025_12_09_093813) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" @@ -380,6 +380,7 @@ ActiveRecord::Schema[8.0].define(version: 2025_12_02_140424) do t.integer "original_number_of_items" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.integer "item_count", default: 0, null: false t.index ["account_id"], name: "index_collections_on_account_id" t.index ["tag_id"], name: "index_collections_on_tag_id" end diff --git a/spec/serializers/rest/base_collection_serializer_spec.rb b/spec/serializers/rest/base_collection_serializer_spec.rb index c988a247e7..5ac6bc615d 100644 --- a/spec/serializers/rest/base_collection_serializer_spec.rb +++ b/spec/serializers/rest/base_collection_serializer_spec.rb @@ -38,20 +38,4 @@ RSpec.describe REST::BaseCollectionSerializer do 'updated_at' => match_api_datetime_format ) end - - describe 'Counting items' do - before do - Fabricate.times(2, :collection_item, collection:) - end - - it 'can count items on demand' do - expect(subject['item_count']).to eq 2 - end - - it 'can use precalculated counts' do - collection.define_singleton_method :item_count, -> { 8 } - - expect(subject['item_count']).to eq 8 - end - end end