Compare commits

...

3 commits

Author SHA1 Message Date
c4a7e7916f Fall back to blank image if alt style has no preview image
This is currently crashing the Rainbow Pool when the Anniversary Techo
would appear, because the asset seems to be missing? The SWF doesn't
seem to exist, nor does its manifest.
2024-11-15 20:04:45 -08:00
217d25edab Handle new colors/species in the Rainbow Pool
Oh right, yeah, we like to do things gracefully around here when
there's no corresponding color/species record yet!

Paying more attention to this, I'm thinking like… it could be a cool
idea to, in modeling, *create* the new color/species record, and just
not have all the attributes filled in yet? Especially now that we're
less dependent on attributes like `standard` to be set for correct
functioning.

But for now, we follow the same strategy we do elsewhere in the app: a
pet type can have `color_id` and `species_id` that don't correspond to
a real record, and we cover over that smoothly.
2024-11-15 19:56:07 -08:00
dd213e8078 Increase the maximum value for pet types' color ID and species ID
Oh dang, we're on color #120 now, and looks like our maximum value is
127. Let's expand that!

I noticed this because I'm writing tests for some stuff, and used "456"
as a placeholder ID number, and it just fully did not work, and I'm
like. Oh.
2024-11-15 19:29:13 -08:00
15 changed files with 194 additions and 24 deletions

View file

@ -17,7 +17,7 @@ class PetStatesController < ApplicationController
protected protected
def find_pet_state def find_pet_state
@pet_type = PetType.matching_name_param(params[:pet_type_name]).first! @pet_type = PetType.find_by_param!(params[:pet_type_name])
@pet_state = @pet_type.pet_states.find(params[:id]) @pet_state = @pet_type.pet_states.find(params[:id])
end end

View file

@ -70,9 +70,7 @@ class PetTypesController < ApplicationController
color_id: params[:color_id], color_id: params[:color_id],
) )
elsif params[:name] elsif params[:name]
color_name, _, species_name = params[:name].rpartition("-") PetType.find_by_param!(params[:name])
raise ActiveRecord::RecordNotFound if species_name.blank?
PetType.matching_name(color_name, species_name).first!
else else
raise "expected params: species_id and color_id, or name" raise "expected params: species_id and color_id, or name"
end end

View file

@ -62,11 +62,10 @@ class AltStyle < ApplicationRecord
"#{series_name} #{name}" "#{series_name} #{name}"
end end
EMPTY_IMAGE_URL = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="
def preview_image_url def preview_image_url
swf_asset = swf_assets.first # Use the image URL for the first asset. Or, fall back to an empty image.
return nil if swf_asset.nil? swf_assets.first&.image_url || EMPTY_IMAGE_URL
swf_asset.image_url
end end
# Given a list of items, return how they look on this alt style. # Given a list of items, return how they look on this alt style.

View file

@ -21,6 +21,10 @@ class Color < ApplicationRecord
end end
end end
def to_param
name? ? human_name : id.to_s
end
def example_pet_type(preferred_species: nil) def example_pet_type(preferred_species: nil)
preferred_species ||= Species.first preferred_species ||= Species.first
pet_types.order([Arel.sql("species_id = ? DESC"), preferred_species.id], pet_types.order([Arel.sql("species_id = ? DESC"), preferred_species.id],
@ -36,4 +40,8 @@ class Color < ApplicationRecord
nil nil
end end
end end
def self.param_to_id(param)
param.match?(/\A\d+\Z/) ? param.to_i : find_by_name!(param).id
end
end end

View file

@ -15,10 +15,6 @@ class PetType < ApplicationRecord
species = Species.find_by_name!(species_name) species = Species.find_by_name!(species_name)
where(color_id: color.id, species_id: species.id) where(color_id: color.id, species_id: species.id)
} }
scope :matching_name_param, ->(name_param) {
color_name, _, species_name = name_param.rpartition("-")
matching_name(color_name, species_name)
}
scope :preferring_species, ->(species_id) { scope :preferring_species, ->(species_id) {
joins(:species).order([Arel.sql("species_id = ? DESC"), species_id]) joins(:species).order([Arel.sql("species_id = ? DESC"), species_id])
} }
@ -116,7 +112,7 @@ class PetType < ApplicationRecord
end end
def to_param def to_param
"#{color.human_name}-#{species.human_name}" "#{possibly_new_color.to_param}-#{possibly_new_species.to_param}"
end end
def fully_labeled? def fully_labeled?
@ -136,6 +132,15 @@ class PetType < ApplicationRecord
pet_states.count { |ps| ps.pose == "UNKNOWN" } pet_states.count { |ps| ps.pose == "UNKNOWN" }
end end
def self.find_by_param!(param)
raise ActiveRecord::RecordNotFound unless param.include?("-")
color_param, _, species_param = param.rpartition("-")
where(
color_id: Color.param_to_id(color_param),
species_id: Species.param_to_id(species_param),
).first!
end
def self.basic_body_ids def self.basic_body_ids
PetType.basic.distinct.pluck(:body_id) PetType.basic.distinct.pluck(:body_id)
end end

View file

@ -16,6 +16,10 @@ class Species < ApplicationRecord
end end
end end
def to_param
name? ? human_name : id.to_s
end
# Given a list of body IDs, return a hash from body ID to Species. # Given a list of body IDs, return a hash from body ID to Species.
# (We assume that each body ID belongs to just one species; if not, which # (We assume that each body ID belongs to just one species; if not, which
# species we return for that body ID is undefined.) # species we return for that body ID is undefined.)
@ -26,4 +30,8 @@ class Species < ApplicationRecord
to_h { |s| [s.id, s] } to_h { |s| [s.id, s] }
species_ids_by_body_id.transform_values { |id| species_by_id[id] } species_ids_by_body_id.transform_values { |id| species_by_id[id] }
end end
def self.param_to_id(param)
param.match?(/\A\d+\Z/) ? param.to_i : find_by_name!(param).id
end
end end

View file

@ -5,11 +5,11 @@
%li %li
= link_to "Rainbow Pool", pet_types_path = link_to "Rainbow Pool", pet_types_path
%li %li
= link_to @pet_type.color.human_name, = link_to @pet_type.possibly_new_color.human_name,
pet_types_path(color: @pet_type.color.human_name) pet_types_path(color: @pet_type.possibly_new_color.human_name)
%li{"data-relation-to-prev": "sibling"} %li{"data-relation-to-prev": "sibling"}
= link_to @pet_type.species.human_name, = link_to @pet_type.possibly_new_species.human_name,
pet_types_path(species: @pet_type.species.human_name) pet_types_path(species: @pet_type.possibly_new_species.human_name)
%li %li
= link_to "Appearances", @pet_type = link_to "Appearances", @pet_type
%li %li

View file

@ -5,11 +5,11 @@
%li %li
= link_to "Rainbow Pool", pet_types_path = link_to "Rainbow Pool", pet_types_path
%li %li
= link_to @pet_type.color.human_name, = link_to @pet_type.possibly_new_color.human_name,
pet_types_path(color: @pet_type.color.human_name) pet_types_path(color: @pet_type.possibly_new_color.human_name)
%li{"data-relation-to-prev": "sibling"} %li{"data-relation-to-prev": "sibling"}
= link_to @pet_type.species.human_name, = link_to @pet_type.possibly_new_species.human_name,
pet_types_path(species: @pet_type.species.human_name) pet_types_path(species: @pet_type.possibly_new_species.human_name)
%li %li
Appearances Appearances

View file

@ -0,0 +1,17 @@
class IncreasePetTypeColorIdAndSpeciesIdLimit < ActiveRecord::Migration[7.2]
def change
reversible do |direction|
change_table :pet_types do |t|
direction.up do
t.change :color_id, :integer, null: false
t.change :species_id, :integer, null: false
end
direction.down do
t.change :color_id, :integer, limit: 1, null: false
t.change :species_id, :integer, limit: 1, null: false
end
end
end
end
end

View file

@ -10,7 +10,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.2].define(version: 2024_10_08_004715) do ActiveRecord::Schema[7.2].define(version: 2024_11_16_031655) do
create_table "alt_styles", charset: "utf8mb4", collation: "utf8mb4_unicode_520_ci", force: :cascade do |t| create_table "alt_styles", charset: "utf8mb4", collation: "utf8mb4_unicode_520_ci", force: :cascade do |t|
t.integer "species_id", null: false t.integer "species_id", null: false
t.integer "color_id", null: false t.integer "color_id", null: false
@ -225,8 +225,8 @@ ActiveRecord::Schema[7.2].define(version: 2024_10_08_004715) do
end end
create_table "pet_types", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_520_ci", force: :cascade do |t| create_table "pet_types", id: :integer, charset: "utf8mb4", collation: "utf8mb4_unicode_520_ci", force: :cascade do |t|
t.integer "color_id", limit: 1, null: false t.integer "color_id", null: false
t.integer "species_id", limit: 1, null: false t.integer "species_id", null: false
t.datetime "created_at", precision: nil, null: false t.datetime "created_at", precision: nil, null: false
t.integer "body_id", limit: 2, null: false t.integer "body_id", limit: 2, null: false
t.string "image_hash", limit: 8 t.string "image_hash", limit: 8

View file

@ -10,3 +10,6 @@ robot:
striped: striped:
id: 77 id: 77
name: striped name: striped
swamp_gas:
id: 93
name: "swamp gas"

19
spec/fixtures/pet_types.yml vendored Normal file
View file

@ -0,0 +1,19 @@
blue_acara:
color_id: 8
species_id: 1
body_id: 123
newcolor_acara:
color_id: 123
species_id: 1
body_id: 123
blue_newspecies:
color_id: 8
species_id: 456
body_id: 123
newcolor_newspecies:
color_id: 123
species_id: 456
body_id: 123

38
spec/models/color_spec.rb Normal file
View file

@ -0,0 +1,38 @@
require 'rails_helper'
RSpec.describe Color do
fixtures :colors
describe '#to_param' do
it("uses name when possible") do
expect(colors(:blue).to_param).to eq "Blue"
end
it("uses spaces for multi-word names") do
expect(colors(:swamp_gas).to_param).to eq "Swamp Gas"
end
it("uses IDs for new colors") do
expect(Color.new(id: 12345).to_param).to eq "12345"
end
end
describe ".param_to_id" do
it("looks up by name") do
expect(Color.param_to_id("blue")).to eq colors(:blue).id
end
it("is case-insensitive for name") do
expect(Color.param_to_id("bLUe")).to eq colors(:blue).id
end
it("returns ID when the param is just a number, even if it doesn't exist") do
expect(Color.param_to_id("123456")).to eq 123456
end
it("raises RecordNotFound if no name matches") do
expect { Color.param_to_id("nonexistant") }.
to raise_error ActiveRecord::RecordNotFound
end
end
end

View file

@ -0,0 +1,41 @@
require 'rails_helper'
RSpec.describe PetType do
fixtures :colors, :species, :pet_types
describe '#to_param' do
it('uses color and species name when possible ("Blue-Acara")') do
expect(pet_types(:blue_acara).to_param).to eq "Blue-Acara"
end
it('uses color ID for new colors (123-Acara)') do
expect(pet_types(:newcolor_acara).to_param).to eq "123-Acara"
end
it('uses species ID for new colors (Blue-456)') do
expect(pet_types(:blue_newspecies).to_param).to eq "Blue-456"
end
it('uses color ID and species ID when both are new (123-456)') do
expect(pet_types(:newcolor_newspecies).to_param).to eq "123-456"
end
end
describe ".find_by_param!" do
it('looks up by species and color name ("Blue-Acara")') do
expect(PetType.find_by_param!("Blue-Acara")).to eq pet_types(:blue_acara)
end
it('looks up by color ID for new colors ("123-Acara")') do
expect(PetType.find_by_param!("123-Acara")).to eq pet_types(:newcolor_acara)
end
it('looks up by species ID for new species ("Blue-456")') do
expect(PetType.find_by_param!("Blue-456")).to eq pet_types(:blue_newspecies)
end
it('looks up by color ID and species ID when both are new ("123-456")') do
expect(PetType.find_by_param!("123-456")).to eq pet_types(:newcolor_newspecies)
end
end
end

View file

@ -0,0 +1,34 @@
require 'rails_helper'
RSpec.describe Species do
fixtures :species
describe '#to_param' do
it("uses name when possible") do
expect(species(:acara).to_param).to eq "Acara"
end
it("uses IDs for new species") do
expect(Species.new(id: 12345).to_param).to eq "12345"
end
end
describe ".param_to_id" do
it("looks up by name") do
expect(Species.param_to_id("acara")).to eq species(:acara).id
end
it("is case-insensitive for name") do
expect(Species.param_to_id("aCaRa")).to eq species(:acara).id
end
it("returns ID when the param is just a number, even if no record exists") do
expect(Species.param_to_id("123456")).to eq 123456
end
it("raises RecordNotFound if no name matches") do
expect { Species.param_to_id("nonexistant") }.
to raise_error ActiveRecord::RecordNotFound
end
end
end