From a00c286ca93ebb94074e8f724e661243b3521c8f Mon Sep 17 00:00:00 2001 From: Miguel de los Reyes Date: Fri, 22 May 2026 18:14:38 +0000 Subject: [PATCH 1/4] Add card_set_id filter --- app/resources/decklist_resource.rb | 10 +++++ .../resources/decklist_resource_reads_spec.rb | 38 +++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/app/resources/decklist_resource.rb b/app/resources/decklist_resource.rb index 949841b..7f122d2 100644 --- a/app/resources/decklist_resource.rb +++ b/app/resources/decklist_resource.rb @@ -44,6 +44,16 @@ class DecklistResource < ApplicationResource end end + # Will return decklists where every card has at least one printing in the specified card set(s). + # Multiple values are treated as the union of card sets, matching the legacy /decklist/find?packs[] behavior. + filter :card_set_id, :string do + eq do |scope, card_set_ids| + legal_card_ids = Printing.where(card_set_id: card_set_ids).select(:card_id) + decklists_with_illegal_cards = DecklistCard.where.not(card_id: legal_card_ids).select(:decklist_id) + scope.where.not(id: decklists_with_illegal_cards) + end + end + attribute :card_slots, :hash attribute :num_cards, :integer attribute :influence_spent, :integer diff --git a/spec/resources/decklist_resource_reads_spec.rb b/spec/resources/decklist_resource_reads_spec.rb index ac566b3..7a30424 100644 --- a/spec/resources/decklist_resource_reads_spec.rb +++ b/spec/resources/decklist_resource_reads_spec.rb @@ -97,6 +97,44 @@ end end + context 'with card_set_id' do + let!(:corp_decklist) { Decklist.find('11111111-1111-1111-1111-111111111111') } + let!(:runner_decklist) { Decklist.find('22222222-2222-2222-2222-222222222222') } + + it 'returns decklists whose cards all have a printing in the set' do + params[:filter] = { card_set_id: { eq: 'core' } } + render + decklist_ids = d.map(&:id) + + expect(decklist_ids).to include(corp_decklist.id) + expect(decklist_ids).to include(runner_decklist.id) + end + + it 'excludes decklists with any card not printed in the set' do + params[:filter] = { card_set_id: { eq: 'midnight_sun' } } + render + decklist_ids = d.map(&:id) + + expect(decklist_ids).not_to include(corp_decklist.id) + expect(decklist_ids).not_to include(runner_decklist.id) + end + + it 'treats multiple card sets as a union of legal cards' do + params[:filter] = { card_set_id: { eq: 'core,midnight_sun' } } + render + decklist_ids = d.map(&:id) + + expect(decklist_ids).to include(corp_decklist.id) + expect(decklist_ids).to include(runner_decklist.id) + end + + it 'combines with faction_id' do + params[:filter] = { card_set_id: { eq: 'core' }, faction_id: { eq: 'criminal' } } + render + expect(d.map(&:id)).to eq([runner_decklist.id]) + end + end + context 'with card_id and exclude_card_id combined' do let!(:corp_decklist) { Decklist.find('11111111-1111-1111-1111-111111111111') } let!(:runner_decklist) { Decklist.find('22222222-2222-2222-2222-222222222222') } From f6a8633b7e1bfa18005abc4ca0b4ba2056607f1d Mon Sep 17 00:00:00 2001 From: Miguel de los Reyes Date: Fri, 22 May 2026 22:23:48 +0000 Subject: [PATCH 2/4] Add decklists_cards index on (card_id, decklist_id) --- ...000_add_card_id_decklist_id_index_to_decklists_cards.rb | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 db/migrate/20260522120000_add_card_id_decklist_id_index_to_decklists_cards.rb diff --git a/db/migrate/20260522120000_add_card_id_decklist_id_index_to_decklists_cards.rb b/db/migrate/20260522120000_add_card_id_decklist_id_index_to_decklists_cards.rb new file mode 100644 index 0000000..ec10166 --- /dev/null +++ b/db/migrate/20260522120000_add_card_id_decklist_id_index_to_decklists_cards.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class AddCardIdDecklistIdIndexToDecklistsCards < ActiveRecord::Migration[8.1] + def change + add_index :decklists_cards, %i[card_id decklist_id] + end +end From 3a16885ce41758b0bbff1a8fd500fe2620a569c9 Mon Sep 17 00:00:00 2001 From: Miguel de los Reyes Date: Sat, 23 May 2026 00:09:20 +0000 Subject: [PATCH 3/4] Add missing schema.rb change --- db/schema.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/db/schema.rb b/db/schema.rb index 613ffc6..e07575c 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.1].define(version: 2026_05_20_044700) do +ActiveRecord::Schema[8.1].define(version: 2026_05_22_120000) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" enable_extension "pgcrypto" @@ -182,6 +182,7 @@ t.string "card_id", null: false t.uuid "decklist_id", null: false t.integer "quantity", null: false + t.index ["card_id", "decklist_id"], name: "index_decklists_cards_on_card_id_and_decklist_id" t.index ["decklist_id", "card_id"], name: "index_decklists_cards_on_decklist_id_and_card_id", unique: true end From 192a17838f04fe25540cef8200f712d7b2647ddf Mon Sep 17 00:00:00 2001 From: Miguel de los Reyes Date: Sat, 23 May 2026 16:30:33 +0000 Subject: [PATCH 4/4] Rename var per suggestion --- app/resources/decklist_resource.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/resources/decklist_resource.rb b/app/resources/decklist_resource.rb index 7f122d2..d18137a 100644 --- a/app/resources/decklist_resource.rb +++ b/app/resources/decklist_resource.rb @@ -48,9 +48,9 @@ class DecklistResource < ApplicationResource # Multiple values are treated as the union of card sets, matching the legacy /decklist/find?packs[] behavior. filter :card_set_id, :string do eq do |scope, card_set_ids| - legal_card_ids = Printing.where(card_set_id: card_set_ids).select(:card_id) - decklists_with_illegal_cards = DecklistCard.where.not(card_id: legal_card_ids).select(:decklist_id) - scope.where.not(id: decklists_with_illegal_cards) + card_ids = Printing.where(card_set_id: card_set_ids).select(:card_id) + decklists_with_other_cards = DecklistCard.where.not(card_id: card_ids).select(:decklist_id) + scope.where.not(id: decklists_with_other_cards) end end