[WV2] Filter colors, using advanced fallbacks

This commit is contained in:
Emi Matchu 2025-11-02 08:46:53 +00:00
parent ddb89dc2fa
commit 58fabad3c2
5 changed files with 73 additions and 10 deletions

View file

@ -78,17 +78,24 @@ class OutfitsController < ApplicationController
end
def new_v2
@colors = Color.alphabetical
@species = Species.alphabetical
# Get selected species and color from params, or default to Blue Acara
species_id = params[:species] || Species.find_by_name("Acara")&.id
color_id = params[:color] || Color.find_by_name("Blue")&.id
@selected_species = params[:species] ? Species.find_by_id(params[:species]) : Species.find_by_name("Acara")
@selected_color = params[:color] ? Color.find_by_id(params[:color]) : Color.find_by_name("Blue")
# Find the pet type (species+color combination)
@selected_species = Species.find_by(id: species_id)
@selected_color = Color.find_by(id: color_id)
@pet_type = PetType.find_by(species_id: species_id, color_id: color_id) if @selected_species && @selected_color
# Load valid colors for the selected species (colors that have existing pet types)
@species = Species.alphabetical
@colors = @selected_species.compatible_colors
# Find the best pet type for this species+color combo
# If the exact combo doesn't exist, this will fall back to a simple color
@pet_type = PetType.for_species_and_color(
species_id: @selected_species.id,
color_id: @selected_color.id
)
# Use the pet type's actual color as the selected color
# (might differ from requested color if we fell back to a simple color)
@selected_color = @pet_type&.color
# Load items from the objects[] parameter
item_ids = params[:objects] || []

View file

@ -48,6 +48,26 @@ class PetType < ApplicationRecord
random_pet_types
end
# Given a species ID and color ID, return the best matching PetType.
#
# If the exact species+color combo exists, return it.
# Otherwise, find the best fallback for that species:
# - Prefer the requested color if available
# - Otherwise prefer simple colors (basic > standard > alphabetical)
#
# This matches the wardrobe behavior where we automatically switch to a valid
# color when the user selects a species that doesn't support their current color.
#
# Returns the PetType, or nil if no pet types exist for this species.
def self.for_species_and_color(species_id:, color_id:)
return nil if species_id.nil?
where(species_id: species_id)
.preferring_color(color_id)
.preferring_simple
.first
end
def as_json(options={})
super({
only: [:id],

View file

@ -34,4 +34,13 @@ class Species < ApplicationRecord
def self.param_to_id(param)
param.match?(/\A\d+\Z/) ? param.to_i : find_by_name!(param).id
end
# Get all colors that are compatible with this species (have pet types)
# Returns an ActiveRecord::Relation of Color records
def compatible_colors
Color.alphabetical
.joins(:pet_types)
.where(pet_types: { species_id: id })
.distinct
end
end

View file

@ -38,4 +38,23 @@ RSpec.describe PetType do
expect(PetType.find_by_param!("123-456")).to eq pet_types(:newcolor_newspecies)
end
end
describe ".for_species_and_color" do
it('returns the exact match when it exists') do
result = PetType.for_species_and_color(species_id: species(:acara), color_id: colors(:blue))
expect(result).to eq pet_types(:blue_acara)
end
it('returns nil when species is nil') do
result = PetType.for_species_and_color(species_id: nil, color_id: colors(:blue))
expect(result).to be_nil
end
it('falls back to a simple color when exact match does not exist') do
# Request a species that exists but with a color that might not
# It should fall back to a basic/standard color for that species
result = PetType.for_species_and_color(species_id: species(:acara), color_id: 999)
expect(result).to eq pet_types(:blue_acara)
end
end
end

View file

@ -1,7 +1,15 @@
require_relative '../rails_helper'
RSpec.describe Species do
fixtures :species
fixtures :species, :colors
describe "#valid_colors_for_species" do
it('returns colors that have pet types for the species') do
# The Blue Acara exists in fixtures, as does a "Color #123 Acara", which we'll ignore.
compatible_colors = species(:acara).compatible_colors
expect(compatible_colors.map(&:id)).to eq [8]
end
end
describe '#to_param' do
it("uses name when possible") do