Refactor item search JSON, add appearances
Preparing to finally move wardrobe-2020's item search to use the main app's API endpoints instead! One blocker I forgot about here: Impress 2020 has actual support for knowing an item's true appearance, like by reading the manifest and stuff, that we haven't really ported over. I feel like maybe I should pause and work on the changes to manifest-archiving that I'd been planning anyway? I'll think about it.
This commit is contained in:
parent
1a1615e0ad
commit
3f449310d6
5 changed files with 60 additions and 42 deletions
|
@ -11,9 +11,11 @@ class ItemsController < ApplicationController
|
|||
else
|
||||
per_page = 30
|
||||
end
|
||||
|
||||
@items = @query.results.paginate(
|
||||
page: params[:page], per_page: per_page)
|
||||
assign_closeted!
|
||||
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
@campaign = Fundraising::Campaign.current rescue nil
|
||||
|
@ -24,13 +26,14 @@ class ItemsController < ApplicationController
|
|||
end
|
||||
}
|
||||
format.json {
|
||||
render json: {items: @items, total_pages: @items.total_pages,
|
||||
query: @query.to_s}
|
||||
}
|
||||
format.js {
|
||||
render json: {items: @items, total_pages: @items.total_pages,
|
||||
query: @query.to_s},
|
||||
callback: params[:callback]
|
||||
render json: {
|
||||
items: @items.as_json(
|
||||
methods: [:nc?, :pb?, :owned?, :wanted?],
|
||||
),
|
||||
appearances: load_appearances,
|
||||
total_pages: @items.total_pages,
|
||||
query: @query.to_s,
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
@ -46,7 +49,6 @@ class ItemsController < ApplicationController
|
|||
@campaign = Fundraising::Campaign.current rescue nil
|
||||
@newest_items = Item.newest.limit(18)
|
||||
}
|
||||
format.js { render json: {error: '$q required'}}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -100,14 +102,20 @@ class ItemsController < ApplicationController
|
|||
def assign_closeted!
|
||||
current_user.assign_closeted_to_items!(@items) if user_signed_in?
|
||||
end
|
||||
|
||||
def load_appearances
|
||||
pet_type_name = params[:with_appearances_for]
|
||||
return {} if pet_type_name.blank?
|
||||
|
||||
pet_type = Item::Search::Query.load_pet_type_by_name(pet_type_name)
|
||||
pet_type.appearances_for(@items.map(&:id))
|
||||
end
|
||||
|
||||
def search_error(e)
|
||||
@items = []
|
||||
respond_to do |format|
|
||||
format.html { flash.now[:alert] = e.message; render }
|
||||
format.json { render :json => {error: e.message} }
|
||||
format.js { render :json => {error: e.message},
|
||||
:callback => params[:callback] }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -122,7 +130,7 @@ class ItemsController < ApplicationController
|
|||
@query = params[:q]
|
||||
raise
|
||||
end
|
||||
elsif q.is_a?(Hash)
|
||||
elsif q.is_a?(ActionController::Parameters)
|
||||
@query = Item::Search::Query.from_params(q, current_user)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -153,11 +153,11 @@ class Item < ApplicationRecord
|
|||
end
|
||||
|
||||
def owned?
|
||||
@owned
|
||||
@owned || false
|
||||
end
|
||||
|
||||
def wanted?
|
||||
@wanted
|
||||
@wanted || false
|
||||
end
|
||||
|
||||
def restricted_zones(options={})
|
||||
|
@ -445,8 +445,8 @@ class Item < ApplicationRecord
|
|||
@parent_swf_asset_relationships_to_update = rels
|
||||
end
|
||||
|
||||
Body = Struct.new(:id, :species)
|
||||
Appearance = Struct.new(:body, :swf_assets)
|
||||
Appearance::Body = Struct.new(:id, :species)
|
||||
def appearances
|
||||
all_swf_assets = swf_assets.to_a
|
||||
|
||||
|
@ -469,7 +469,7 @@ class Item < ApplicationRecord
|
|||
swf_assets_by_body_id.map do |body_id, body_specific_assets|
|
||||
swf_assets_for_body = body_specific_assets + swf_assets_for_all_bodies
|
||||
species = Species.with_body_id(body_id).first!
|
||||
body = Body.new(body_id, species)
|
||||
body = Appearance::Body.new(body_id, species)
|
||||
Appearance.new(body, swf_assets_for_body)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -46,17 +46,10 @@ class Item
|
|||
Filter.restricts(value) :
|
||||
Filter.not_restricts(value))
|
||||
when 'fits'
|
||||
color_name, species_name = value.split('-')
|
||||
begin
|
||||
pet_type = PetType.matching_name(color_name, species_name).first!
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
message = I18n.translate('items.search.errors.not_found.pet_type',
|
||||
name1: color_name.capitalize, name2: species_name.capitalize)
|
||||
raise Item::Search::Error, message
|
||||
end
|
||||
pet_type = load_pet_type_by_name(value)
|
||||
filters << (is_positive ?
|
||||
Filter.fits(pet_type.body_id, color_name, species_name) :
|
||||
Filter.not_fits(pet_type.body_id, color_name, species_name))
|
||||
Filter.fits(pet_type.body_id, value.downcase) :
|
||||
Filter.not_fits(pet_type.body_id, value.downcase))
|
||||
when 'species'
|
||||
begin
|
||||
species = Species.find_by_name!(value)
|
||||
|
@ -139,9 +132,11 @@ class Item
|
|||
pet_type = PetType.find(value)
|
||||
color_name = pet_type.color.name
|
||||
species_name = pet_type.species.name
|
||||
# NOTE: Some color syntaxes are weird, like `fits:"polka dot-aisha"`!
|
||||
value = "#{color_name}-#{species_name}"
|
||||
filters << (is_positive ?
|
||||
Filter.fits(pet_type.body_id, color_name, species_name) :
|
||||
Filter.not_fits(pet_type.body_id, color_name, species_name))
|
||||
Filter.fits(pet_type.body_id, value) :
|
||||
Filter.not_fits(pet_type.body_id, value))
|
||||
when 'user_closet_hanger_ownership'
|
||||
case value
|
||||
when 'true'
|
||||
|
@ -160,6 +155,18 @@ class Item
|
|||
|
||||
self.new(filters, user)
|
||||
end
|
||||
|
||||
def self.load_pet_type_by_name(pet_type_string)
|
||||
color_name, species_name = pet_type_string.split("-")
|
||||
|
||||
begin
|
||||
PetType.matching_name(color_name, species_name).first!
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
message = I18n.translate('items.search.errors.not_found.pet_type',
|
||||
name1: color_name.capitalize, name2: species_name.capitalize)
|
||||
raise Item::Search::Error, message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Error < Exception
|
||||
|
@ -211,15 +218,11 @@ class Item
|
|||
self.new Item.not_restricts(value), "-restricts:#{q value}"
|
||||
end
|
||||
|
||||
def self.fits(body_id, color_name, species_name)
|
||||
# NOTE: Some color syntaxes are weird, like `fits:"polka dot-aisha"`!
|
||||
value = "#{color_name.downcase}-#{species_name.downcase}"
|
||||
def self.fits(body_id, value)
|
||||
self.new Item.fits(body_id), "fits:#{q value}"
|
||||
end
|
||||
|
||||
def self.not_fits(body_id, color_name, species_name)
|
||||
# NOTE: Some color syntaxes are weird, like `fits:"polka dot-aisha"`!
|
||||
value = "#{color_name.downcase}-#{species_name.downcase}"
|
||||
def self.not_fits(body_id, value)
|
||||
self.new Item.not_fits(body_id), "-fits:#{q value}"
|
||||
end
|
||||
|
||||
|
@ -277,14 +280,6 @@ class Item
|
|||
def self.q(value)
|
||||
/\s/.match(value) ? '"' + value + '"' : value
|
||||
end
|
||||
|
||||
def self.build_fits_filter_text(color_name, species_name)
|
||||
# NOTE: Colors like "Polka Dot" must be written as
|
||||
# `fits:"polka dot-aisha"`.
|
||||
value = "#{color_name.downcase}-#{species_name.downcase}"
|
||||
value = '"' + value + '"' if value.include? ' '
|
||||
"fits:#{value}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -178,6 +178,18 @@ class PetType < ApplicationRecord
|
|||
}.first
|
||||
end
|
||||
|
||||
def appearances_for(item_ids)
|
||||
# First, load all the relationships for these items that also fit this
|
||||
# body.
|
||||
relationships = ParentSwfAssetRelationship.includes(:swf_asset).
|
||||
where(parent_type: "Item", parent_id: item_ids).
|
||||
where(swf_asset: {body_id: [body_id, 0]})
|
||||
|
||||
# Then, convert this into a hash from item ID to SWF assets.
|
||||
assets_by_item_id = relationships.group_by(&:parent_id).
|
||||
transform_values { |rels| rels.map(&:swf_asset) }
|
||||
end
|
||||
|
||||
def self.all_by_ids_or_children(ids, pet_states)
|
||||
pet_states_by_pet_type_id = {}
|
||||
pet_states.each do |pet_state|
|
||||
|
|
|
@ -82,7 +82,10 @@ class SwfAsset < ApplicationRecord
|
|||
scope :object_assets, -> { where(:type => Item::SwfAssetType) }
|
||||
scope :for_item_ids, ->(item_ids) {
|
||||
joins(:parent_swf_asset_relationships).
|
||||
where(ParentSwfAssetRelationship.arel_table[:parent_id].in(item_ids))
|
||||
where(parent_swf_asset_relationships: {
|
||||
parent_type: "Item",
|
||||
parent_id: item_ids,
|
||||
})
|
||||
}
|
||||
scope :with_parent_ids, -> {
|
||||
select('swf_assets.*, parents_swf_assets.parent_id')
|
||||
|
|
Loading…
Reference in a new issue