forked from OpenNeo/impress
Replace swf_assets#index with item_appearances#index
Preparing a better endpoint for wardrobe-2020 to use! I deleted the now-unused swf_assets#index endpoint, and replaced it with an "appearances" concept that isn't exactly reflected in the database models but is a _lot_ easier for clients to work with imo. Note that this was a big part of the motivation for the recent `manifest_url` work—in this draft, I'm probably gonna have the client request the manifest, rather than use impress-2020's trick of caching it in the database! There's a bit of a perf penalty, but I think that's a simpler starting point, and I have a hunch I'll be able to make up the perf difference once we have the impress-media-server managing more of these responsibilities.
This commit is contained in:
parent
3b59823fc4
commit
010f64264f
6 changed files with 58 additions and 90 deletions
6
app/controllers/item_appearances_controller.rb
Normal file
6
app/controllers/item_appearances_controller.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
class ItemAppearancesController < ApplicationController
|
||||||
|
def index
|
||||||
|
@item = Item.find(params[:item_id])
|
||||||
|
render json: @item.appearances
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,60 +1,4 @@
|
||||||
class SwfAssetsController < ApplicationController
|
class SwfAssetsController < ApplicationController
|
||||||
def index
|
|
||||||
if params[:item_id]
|
|
||||||
item = Item.find(params[:item_id])
|
|
||||||
@swf_assets = item.swf_assets.includes_depth
|
|
||||||
if params[:body_id]
|
|
||||||
@swf_assets = @swf_assets.fitting_body_id(params[:body_id])
|
|
||||||
else
|
|
||||||
if item.special_color
|
|
||||||
@swf_assets = @swf_assets.fitting_color(item.special_color)
|
|
||||||
else
|
|
||||||
@swf_assets = @swf_assets.fitting_standard_body_ids
|
|
||||||
end
|
|
||||||
json = @swf_assets.all.group_by(&:body_id)
|
|
||||||
end
|
|
||||||
elsif params[:pet_type_id] && params[:item_ids]
|
|
||||||
pet_type = PetType.find(params[:pet_type_id])
|
|
||||||
|
|
||||||
@swf_assets = SwfAsset.object_assets.includes_depth.
|
|
||||||
fitting_body_id(pet_type.body_id).
|
|
||||||
for_item_ids(params[:item_ids]).
|
|
||||||
with_parent_ids
|
|
||||||
json = @swf_assets.map { |a| a.as_json(:parent_id => a.parent_id.to_i, :for => 'wardrobe') }
|
|
||||||
elsif params[:pet_state_id]
|
|
||||||
@swf_assets = PetState.find(params[:pet_state_id]).swf_assets.
|
|
||||||
includes_depth.all
|
|
||||||
pet_state_id = params[:pet_state_id].to_i
|
|
||||||
json = @swf_assets.map { |a| a.as_json(:parent_id => pet_state_id, :for => 'wardrobe') }
|
|
||||||
elsif params[:pet_type_id]
|
|
||||||
@swf_assets = PetType.find(params[:pet_type_id]).pet_states.emotion_order
|
|
||||||
.first.swf_assets.includes_depth
|
|
||||||
elsif params[:ids]
|
|
||||||
@swf_assets = []
|
|
||||||
if params[:ids][:biology]
|
|
||||||
@swf_assets += SwfAsset.includes_depth.biology_assets.where(:remote_id => params[:ids][:biology]).all
|
|
||||||
end
|
|
||||||
if params[:ids][:object]
|
|
||||||
@swf_assets += SwfAsset.includes_depth.object_assets.where(:remote_id => params[:ids][:object]).all
|
|
||||||
end
|
|
||||||
elsif params[:body_id] && params[:item_ids]
|
|
||||||
# DEPRECATED in favor of pet_type_id and item_ids
|
|
||||||
swf_assets = SwfAsset.arel_table
|
|
||||||
@swf_assets = SwfAsset.includes_depth.object_assets.
|
|
||||||
select('swf_assets.*, parents_swf_assets.parent_id').
|
|
||||||
fitting_body_id(params[:body_id]).
|
|
||||||
for_item_ids(params[:item_ids])
|
|
||||||
json = @swf_assets.map { |a| a.as_json(:parent_id => a.parent_id.to_i, :for => 'wardrobe') }
|
|
||||||
end
|
|
||||||
if @swf_assets
|
|
||||||
@swf_assets = @swf_assets.all unless @swf_assets.is_a? Array
|
|
||||||
json = @swf_assets unless json
|
|
||||||
else
|
|
||||||
json = nil
|
|
||||||
end
|
|
||||||
render :json => json
|
|
||||||
end
|
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@swf_asset = SwfAsset.find params[:id]
|
@swf_asset = SwfAsset.find params[:id]
|
||||||
render :json => @swf_asset
|
render :json => @swf_asset
|
||||||
|
|
|
@ -512,16 +512,29 @@ class Item < ApplicationRecord
|
||||||
@parent_swf_asset_relationships_to_update = rels
|
@parent_swf_asset_relationships_to_update = rels
|
||||||
end
|
end
|
||||||
|
|
||||||
def needed_translations
|
Appearance = Struct.new(:body_id, :swf_assets)
|
||||||
translatable_locales = Set.new(I18n.locales_with_neopets_language_code)
|
def appearances
|
||||||
translated_locales = Set.new(translations.map(&:locale))
|
all_swf_assets = swf_assets.to_a
|
||||||
translatable_locales - translated_locales
|
|
||||||
end
|
|
||||||
|
|
||||||
def method_cached?(method_name)
|
# If there are no assets yet, there are no appearances.
|
||||||
# No methods are cached on a full item. This is for duck typing with item
|
return [] if all_swf_assets.empty?
|
||||||
# proxies.
|
|
||||||
false
|
# Get all SWF assets, and separate the ones that fit everyone (body_id=0).
|
||||||
|
swf_assets_by_body_id = all_swf_assets.group_by(&:body_id)
|
||||||
|
swf_assets_for_all_bodies = swf_assets_by_body_id.delete(0) || []
|
||||||
|
|
||||||
|
# If there are no body-specific assets, return one appearance for them all.
|
||||||
|
if swf_assets_by_body_id.empty?
|
||||||
|
return Appearance.new(0, swf_assets_for_all_bodies)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Otherwise, create an appearance for each real (nonzero) body ID. We don't
|
||||||
|
# generally expect body_id = 0 and body_id != 0 to mix, but if they do,
|
||||||
|
# uhh, let's merge the body_id = 0 ones in?
|
||||||
|
swf_assets_by_body_id.map do |body_id, body_specific_assets|
|
||||||
|
swf_assets_for_body = body_specific_assets + swf_assets_for_all_bodies
|
||||||
|
Appearance.new(body_id, swf_assets_for_body)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.all_by_ids_or_children(ids, swf_assets)
|
def self.all_by_ids_or_children(ids, swf_assets)
|
||||||
|
|
|
@ -96,22 +96,30 @@ class SwfAsset < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def as_json(options={})
|
def as_json(options={})
|
||||||
json = {
|
super({
|
||||||
:id => remote_id,
|
only: [:id],
|
||||||
:type => type,
|
methods: [:zone, :restricted_zones, :urls]
|
||||||
:depth => depth,
|
}.merge(options))
|
||||||
:body_id => body_id,
|
end
|
||||||
:zone_id => zone_id,
|
|
||||||
:zones_restrict => zones_restrict,
|
def urls
|
||||||
:is_body_specific => body_specific?,
|
{
|
||||||
# Now that we don't proactively convert images anymore, let's just always
|
swf: url,
|
||||||
# say `has_image: true` when sending data to the frontend, so it'll use the
|
png: image_url,
|
||||||
# new URLs anyway!
|
manifest: manifest_url,
|
||||||
:has_image => true,
|
|
||||||
:images => images
|
|
||||||
}
|
}
|
||||||
json[:parent_id] = options[:parent_id] if options[:parent_id]
|
end
|
||||||
json
|
|
||||||
|
def restricted_zone_ids
|
||||||
|
[].tap do |ids|
|
||||||
|
zones_restrict.chars.each_with_index do |bit, index|
|
||||||
|
ids << index + 1 if bit == "1"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def restricted_zones
|
||||||
|
Zone.where(id: restricted_zone_ids)
|
||||||
end
|
end
|
||||||
|
|
||||||
def body_specific?
|
def body_specific?
|
||||||
|
|
|
@ -18,6 +18,10 @@ class Zone < ActiveRecord::Base
|
||||||
}
|
}
|
||||||
scope :for_items, -> { where(arel_table[:type_id].gt(1)) }
|
scope :for_items, -> { where(arel_table[:type_id].gt(1)) }
|
||||||
|
|
||||||
|
def as_json(options={})
|
||||||
|
super({only: [:id, :depth, :label]}.merge(options))
|
||||||
|
end
|
||||||
|
|
||||||
def uncertain_label
|
def uncertain_label
|
||||||
@sometimes ? "#{label} sometimes" : label
|
@sometimes ? "#{label} sometimes" : label
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,25 +7,18 @@ OpenneoImpressItems::Application.routes.draw do
|
||||||
get '/wardrobe' => redirect('/outfits/new')
|
get '/wardrobe' => redirect('/outfits/new')
|
||||||
get '/start/:color_name/:species_name' => 'outfits#start'
|
get '/start/:color_name/:species_name' => 'outfits#start'
|
||||||
|
|
||||||
# DEPRECATED
|
|
||||||
get '/bodies/:body_id/swf_assets.json' => 'swf_assets#index', :as => :body_swf_assets
|
|
||||||
|
|
||||||
get '/items/:item_id/swf_assets.json' => 'swf_assets#index', :as => :item_swf_assets
|
|
||||||
get '/items/:item_id/bodies/:body_id/swf_assets.json' => 'swf_assets#index', :as => :item_swf_assets_for_body_id
|
|
||||||
get '/pet_types/:pet_type_id/swf_assets.json' => 'swf_assets#index', :as => :pet_type_swf_assets
|
|
||||||
get '/pet_types/:pet_type_id/items/swf_assets.json' => 'swf_assets#index', :as => :item_swf_assets_for_pet_type
|
|
||||||
get '/pet_states/:pet_state_id/swf_assets.json' => 'swf_assets#index', :as => :pet_state_swf_assets
|
|
||||||
get '/species/:species_id/color/:color_id/pet_type.json' => 'pet_types#show'
|
get '/species/:species_id/color/:color_id/pet_type.json' => 'pet_types#show'
|
||||||
|
|
||||||
resources :contributions, :only => [:index]
|
resources :contributions, :only => [:index]
|
||||||
resources :items, :only => [:index, :show] do
|
resources :items, :only => [:index, :show] do
|
||||||
|
resources :appearances, controller: 'item_appearances', only: [:index]
|
||||||
collection do
|
collection do
|
||||||
get :needed
|
get :needed
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
resources :outfits, :only => [:show, :create, :update, :destroy]
|
resources :outfits, :only => [:show, :create, :update, :destroy]
|
||||||
resources :pet_attributes, :only => [:index]
|
resources :pet_attributes, :only => [:index]
|
||||||
resources :swf_assets, :only => [:index, :show] do
|
resources :swf_assets, :only => [:show] do
|
||||||
collection do
|
collection do
|
||||||
get :links
|
get :links
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue