Compare commits
No commits in common. "3ac9e7ce6994352171bdbd26f2a0e7fb91c0dedd" and "0705f66f6db85916aa4bea45f1000cca1dbff473" have entirely different histories.
3ac9e7ce69
...
0705f66f6d
12 changed files with 79 additions and 95 deletions
|
|
@ -235,6 +235,7 @@ class ClosetHangersController < ApplicationController
|
||||||
lists,
|
lists,
|
||||||
hangers_scope: hangers_scope,
|
hangers_scope: hangers_scope,
|
||||||
items_scope: items_scope,
|
items_scope: items_scope,
|
||||||
|
item_translations_scope: item_translations_scope,
|
||||||
)
|
)
|
||||||
lists.group_by(&:hangers_owned)
|
lists.group_by(&:hangers_owned)
|
||||||
end
|
end
|
||||||
|
|
@ -247,6 +248,7 @@ class ClosetHangersController < ApplicationController
|
||||||
ClosetHanger.preload_items(
|
ClosetHanger.preload_items(
|
||||||
hangers,
|
hangers,
|
||||||
items_scope: items_scope,
|
items_scope: items_scope,
|
||||||
|
item_translations_scope: item_translations_scope,
|
||||||
)
|
)
|
||||||
hangers.group_by(&:owned)
|
hangers.group_by(&:owned)
|
||||||
else
|
else
|
||||||
|
|
@ -259,8 +261,12 @@ class ClosetHangersController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def items_scope
|
def items_scope
|
||||||
Item.select(:id, :name, :description, :thumbnail_url, :rarity_index,
|
Item.select(:id, :thumbnail_url, :rarity_index, :is_manually_nc)
|
||||||
:is_manually_nc)
|
end
|
||||||
|
|
||||||
|
def item_translations_scope
|
||||||
|
Item::Translation.select(:id, :item_id, :locale, :name, :description).
|
||||||
|
where(locale: I18n.locale)
|
||||||
end
|
end
|
||||||
|
|
||||||
def owned
|
def owned
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ class ContributionsController < ApplicationController
|
||||||
Contribution.preload_contributeds_and_parents(
|
Contribution.preload_contributeds_and_parents(
|
||||||
@contributions,
|
@contributions,
|
||||||
:scopes => {
|
:scopes => {
|
||||||
|
'Item' => Item.includes(:translations),
|
||||||
'PetType' => PetType.includes(:species, :color),
|
'PetType' => PetType.includes(:species, :color),
|
||||||
'AltStyle' => AltStyle.includes(:species, :color),
|
'AltStyle' => AltStyle.includes(:species, :color),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,10 @@ class ItemsController < ApplicationController
|
||||||
else
|
else
|
||||||
per_page = 30
|
per_page = 30
|
||||||
end
|
end
|
||||||
@items = @query.results.paginate(
|
# Note that we sort by name by hand, since we might have to use
|
||||||
page: params[:page], per_page: per_page)
|
# fallbacks after the fact
|
||||||
|
@items = @query.results.includes(:translations).
|
||||||
|
paginate(page: params[:page], per_page: per_page)
|
||||||
assign_closeted!
|
assign_closeted!
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html {
|
format.html {
|
||||||
|
|
@ -44,7 +46,7 @@ class ItemsController < ApplicationController
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html {
|
format.html {
|
||||||
@campaign = Fundraising::Campaign.current rescue nil
|
@campaign = Fundraising::Campaign.current rescue nil
|
||||||
@newest_items = Item.newest.limit(18)
|
@newest_items = Item.newest.includes(:translations).limit(18)
|
||||||
}
|
}
|
||||||
format.js { render json: {error: '$q required'}}
|
format.js { render json: {error: '$q required'}}
|
||||||
end
|
end
|
||||||
|
|
@ -86,7 +88,8 @@ class ItemsController < ApplicationController
|
||||||
raise ActiveRecord::RecordNotFound, 'Pet type not found'
|
raise ActiveRecord::RecordNotFound, 'Pet type not found'
|
||||||
end
|
end
|
||||||
|
|
||||||
@items = @pet_type.needed_items.order(:name)
|
@items = @pet_type.needed_items.includes(:translations).
|
||||||
|
alphabetize_by_translations
|
||||||
assign_closeted!
|
assign_closeted!
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,8 @@ class OutfitsController < ApplicationController
|
||||||
@species = Species.alphabetical
|
@species = Species.alphabetical
|
||||||
|
|
||||||
newest_items = Item.newest.
|
newest_items = Item.newest.
|
||||||
select(:id, :name, :updated_at, :thumbnail_url, :rarity_index, :is_manually_nc)
|
select(:id, :updated_at, :thumbnail_url, :rarity_index, :is_manually_nc).
|
||||||
.limit(18)
|
includes(:translations).limit(18)
|
||||||
@newest_modeled_items, @newest_unmodeled_items =
|
@newest_modeled_items, @newest_unmodeled_items =
|
||||||
newest_items.partition(&:predicted_fully_modeled?)
|
newest_items.partition(&:predicted_fully_modeled?)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,10 @@ class PetsController < ApplicationController
|
||||||
# return modeling_disabled unless user_signed_in? && current_user.admin?
|
# return modeling_disabled unless user_signed_in? && current_user.admin?
|
||||||
|
|
||||||
raise Pet::PetNotFound unless params[:name]
|
raise Pet::PetNotFound unless params[:name]
|
||||||
@pet = Pet.load(params[:name])
|
@pet = Pet.load(
|
||||||
|
params[:name],
|
||||||
|
:item_scope => Item.includes(:translations),
|
||||||
|
)
|
||||||
points = contribute(current_user, @pet)
|
points = contribute(current_user, @pet)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ class SitemapController < ApplicationController
|
||||||
|
|
||||||
def index
|
def index
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.xml { @items = Item.sitemap }
|
format.xml { @items = Item.includes(:translations).sitemap }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,9 @@ class ClosetHanger < ApplicationRecord
|
||||||
validate :list_belongs_to_user
|
validate :list_belongs_to_user
|
||||||
|
|
||||||
scope :alphabetical_by_item_name, -> {
|
scope :alphabetical_by_item_name, -> {
|
||||||
i = Item.arel_table
|
it = Item::Translation.arel_table
|
||||||
joins(:item).order(i[:name].asc)
|
joins(:item => :translations).where(it[:locale].eq(I18n.locale)).
|
||||||
|
order(it[:name].asc)
|
||||||
}
|
}
|
||||||
scope :trading, -> {
|
scope :trading, -> {
|
||||||
ch = arel_table
|
ch = arel_table
|
||||||
|
|
@ -85,24 +86,28 @@ class ClosetHanger < ApplicationRecord
|
||||||
base
|
base
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: Is the performance improvement on this actually much better than just
|
|
||||||
# `includes`, now that `Item::Translation` records aren't part of it anymore?
|
|
||||||
def self.preload_items(
|
def self.preload_items(
|
||||||
hangers,
|
hangers,
|
||||||
items_scope: Item.all
|
items_scope: Item.all,
|
||||||
|
item_translations_scope: Item::Translation.all
|
||||||
)
|
)
|
||||||
# Preload the records we need. (This is like `includes`, but `includes`
|
# Preload the records we need. (This is like `includes`, but `includes`
|
||||||
# always selects all fields for all records, and we give the caller the
|
# always selects all fields for all records, and we give the caller the
|
||||||
# opportunity to specify which fields it actually wants via scope!)
|
# opportunity to specify which fields it actually wants via scope!)
|
||||||
items = items_scope.where(id: hangers.map(&:item_id))
|
items = items_scope.where(id: hangers.map(&:item_id))
|
||||||
|
translations = item_translations_scope.where(item_id: items.map(&:id))
|
||||||
|
|
||||||
# Group the records by relevant IDs.
|
# Group the records by relevant IDs.
|
||||||
|
translations_by_item_id = translations.group_by(&:item_id)
|
||||||
items_by_id = items.to_h { |i| [i.id, i] }
|
items_by_id = items.to_h { |i| [i.id, i] }
|
||||||
|
|
||||||
# Assign the preloaded records to the records they belong to. (This is like
|
# Assign the preloaded records to the records they belong to. (This is like
|
||||||
# doing e.g. h.item = ..., but that's a database write - we actually just
|
# doing e.g. i.translations = ..., but that's a database write - we
|
||||||
# want to set the `item` field itself directly! Hacky, ripped from how
|
# actually just want to set the `translations` field itself directly!
|
||||||
# `ActiveRecord::Associations::Preloader` does it!)
|
# Hacky, ripped from how `ActiveRecord::Associations::Preloader` does it!)
|
||||||
|
items.each do |item|
|
||||||
|
item.association(:translations).target = translations_by_item_id[item.id]
|
||||||
|
end
|
||||||
hangers.each do |hanger|
|
hangers.each do |hanger|
|
||||||
hanger.association(:item).target = items_by_id[hanger.item_id]
|
hanger.association(:item).target = items_by_id[hanger.item_id]
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,8 @@ class ClosetList < ApplicationRecord
|
||||||
def self.preload_items(
|
def self.preload_items(
|
||||||
lists,
|
lists,
|
||||||
hangers_scope: ClosetHanger.all,
|
hangers_scope: ClosetHanger.all,
|
||||||
items_scope: Item.all
|
items_scope: Item.all,
|
||||||
|
item_translations_scope: Item::Translation.all
|
||||||
)
|
)
|
||||||
# Preload the records we need. (This is like `includes`, but `includes`
|
# Preload the records we need. (This is like `includes`, but `includes`
|
||||||
# always selects all fields for all records, and we give the caller the
|
# always selects all fields for all records, and we give the caller the
|
||||||
|
|
@ -56,9 +57,9 @@ class ClosetList < ApplicationRecord
|
||||||
hangers_by_list_id = hangers.group_by(&:list_id)
|
hangers_by_list_id = hangers.group_by(&:list_id)
|
||||||
|
|
||||||
# Assign the preloaded records to the records they belong to. (This is like
|
# Assign the preloaded records to the records they belong to. (This is like
|
||||||
# doing e.g. h.item = ..., but that's a database write - we actually just
|
# doing e.g. i.translations = ..., but that's a database write - we
|
||||||
# want to set the `item` field itself directly! Hacky, ripped from how
|
# actually just want to set the `translations` field itself directly!
|
||||||
# `ActiveRecord::Associations::Preloader` does it!)
|
# Hacky, ripped from how `ActiveRecord::Associations::Preloader` does it!)
|
||||||
lists.each do |list|
|
lists.each do |list|
|
||||||
list.association(:hangers).target = hangers_by_list_id[list.id]
|
list.association(:hangers).target = hangers_by_list_id[list.id]
|
||||||
end
|
end
|
||||||
|
|
@ -67,6 +68,7 @@ class ClosetList < ApplicationRecord
|
||||||
ClosetHanger.preload_items(
|
ClosetHanger.preload_items(
|
||||||
hangers,
|
hangers,
|
||||||
items_scope: items_scope,
|
items_scope: items_scope,
|
||||||
|
item_translations_scope: item_translations_scope,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,7 @@ class Item < ApplicationRecord
|
||||||
|
|
||||||
SwfAssetType = 'object'
|
SwfAssetType = 'object'
|
||||||
|
|
||||||
# Keep the reference to the deprecated `Item::Translation` record, but don't
|
translates :name, :description, :rarity
|
||||||
# bind it directly to any attributes anymore. We have some temporary writers
|
|
||||||
# that hack around the API to keep the attributes synced, while no longer
|
|
||||||
# reading *from* them by default.
|
|
||||||
# TODO: Remove once we're all done with translations, both here and in 2020!
|
|
||||||
translates
|
|
||||||
|
|
||||||
has_many :closet_hangers
|
has_many :closet_hangers
|
||||||
has_one :contribution, :as => :contributed, :inverse_of => :contributed
|
has_one :contribution, :as => :contributed, :inverse_of => :contributed
|
||||||
|
|
@ -28,6 +23,13 @@ class Item < ApplicationRecord
|
||||||
cattr_reader :per_page
|
cattr_reader :per_page
|
||||||
@@per_page = 30
|
@@per_page = 30
|
||||||
|
|
||||||
|
scope :alphabetize_by_translations, ->(locale) {
|
||||||
|
locale = locale or I18n.locale
|
||||||
|
it = Item::Translation.arel_table
|
||||||
|
joins(:translations).where(it[:locale].eq('en')).
|
||||||
|
order(it[:name].asc)
|
||||||
|
}
|
||||||
|
|
||||||
scope :newest, -> {
|
scope :newest, -> {
|
||||||
order(arel_table[:created_at].desc) if arel_table[:created_at]
|
order(arel_table[:created_at].desc) if arel_table[:created_at]
|
||||||
}
|
}
|
||||||
|
|
@ -37,10 +39,14 @@ class Item < ApplicationRecord
|
||||||
scope :with_closet_hangers, -> { joins(:closet_hangers) }
|
scope :with_closet_hangers, -> { joins(:closet_hangers) }
|
||||||
|
|
||||||
scope :name_includes, ->(value, locale = I18n.locale) {
|
scope :name_includes, ->(value, locale = I18n.locale) {
|
||||||
Item.where("name LIKE ?", "%" + sanitize_sql_like(value) + "%")
|
it = Item::Translation.arel_table
|
||||||
|
Item.joins(:translations).where(it[:locale].eq(locale)).
|
||||||
|
where(it[:name].matches('%' + sanitize_sql_like(value) + '%'))
|
||||||
}
|
}
|
||||||
scope :name_excludes, ->(value, locale = I18n.locale) {
|
scope :name_excludes, ->(value, locale = I18n.locale) {
|
||||||
Item.where("name NOT LIKE ?", "%" + sanitize_sql_like(value) + "%")
|
it = Item::Translation.arel_table
|
||||||
|
Item.joins(:translations).where(it[:locale].eq(locale)).
|
||||||
|
where(it[:name].matches('%' + sanitize_sql_like(value) + '%').not)
|
||||||
}
|
}
|
||||||
scope :is_nc, -> {
|
scope :is_nc, -> {
|
||||||
i = Item.arel_table
|
i = Item.arel_table
|
||||||
|
|
@ -51,12 +57,16 @@ class Item < ApplicationRecord
|
||||||
where(i[:rarity_index].in(Item::NCRarities).or(i[:is_manually_nc].eq(true)).not)
|
where(i[:rarity_index].in(Item::NCRarities).or(i[:is_manually_nc].eq(true)).not)
|
||||||
}
|
}
|
||||||
scope :is_pb, -> {
|
scope :is_pb, -> {
|
||||||
where('description LIKE ?',
|
it = Item::Translation.arel_table
|
||||||
'%' + sanitize_sql_like(PAINTBRUSH_SET_DESCRIPTION) + '%')
|
joins(:translations).where(it[:locale].eq('en')).
|
||||||
|
where('description LIKE ?',
|
||||||
|
'%' + sanitize_sql_like(PAINTBRUSH_SET_DESCRIPTION) + '%')
|
||||||
}
|
}
|
||||||
scope :is_not_pb, -> {
|
scope :is_not_pb, -> {
|
||||||
where('description NOT LIKE ?',
|
it = Item::Translation.arel_table
|
||||||
'%' + sanitize_sql_like(PAINTBRUSH_SET_DESCRIPTION) + '%')
|
joins(:translations).where(it[:locale].eq('en')).
|
||||||
|
where('description NOT LIKE ?',
|
||||||
|
'%' + sanitize_sql_like(PAINTBRUSH_SET_DESCRIPTION) + '%')
|
||||||
}
|
}
|
||||||
scope :occupies, ->(zone_label) {
|
scope :occupies, ->(zone_label) {
|
||||||
zone_ids = Zone.matching_label(zone_label).map(&:id)
|
zone_ids = Zone.matching_label(zone_label).map(&:id)
|
||||||
|
|
@ -112,30 +122,12 @@ class Item < ApplicationRecord
|
||||||
distinct
|
distinct
|
||||||
}
|
}
|
||||||
|
|
||||||
# Temporary writers to keep the English translation record updated, while
|
|
||||||
# primarily using the attributes on the model itself.
|
|
||||||
#
|
|
||||||
# Once this app and DTI 2020 are both comfortably off the translation system,
|
|
||||||
# we can remove this!
|
|
||||||
def name=(new_name)
|
|
||||||
globalize.write(:en, :name, new_name)
|
|
||||||
write_attribute(:name, new_name)
|
|
||||||
end
|
|
||||||
def description=(new_description)
|
|
||||||
globalize.write(:en, :description, new_description)
|
|
||||||
write_attribute(:description, new_description)
|
|
||||||
end
|
|
||||||
def rarity=(new_rarity)
|
|
||||||
globalize.write(:en, :rarity, new_rarity)
|
|
||||||
write_attribute(:rarity, new_rarity)
|
|
||||||
end
|
|
||||||
|
|
||||||
def nc_trade_value
|
def nc_trade_value
|
||||||
return nil unless nc?
|
return nil unless nc?
|
||||||
begin
|
begin
|
||||||
OwlsValueGuide.find_by_name(name)
|
OwlsValueGuide.find_by_name(name(:en))
|
||||||
rescue OwlsValueGuide::NotFound => error
|
rescue OwlsValueGuide::NotFound => error
|
||||||
Rails.logger.debug("No NC trade value listed for #{name} (#{id})")
|
Rails.logger.debug("No NC trade value listed for #{name(:en)} (#{id})")
|
||||||
return nil
|
return nil
|
||||||
rescue OwlsValueGuide::NetworkError => error
|
rescue OwlsValueGuide::NetworkError => error
|
||||||
Rails.logger.error("Couldn't load nc_trade_value: #{error.full_message}")
|
Rails.logger.error("Couldn't load nc_trade_value: #{error.full_message}")
|
||||||
|
|
@ -448,16 +440,16 @@ class Item < ApplicationRecord
|
||||||
species_support_strs = info['species_support'] || []
|
species_support_strs = info['species_support'] || []
|
||||||
self.species_support_ids = species_support_strs.map(&:to_i)
|
self.species_support_ids = species_support_strs.map(&:to_i)
|
||||||
|
|
||||||
self.name = info['name']
|
self.name_translations = {locale => info['name']}
|
||||||
self.description = info['description']
|
|
||||||
self.thumbnail_url = info['thumbnail_url']
|
attribute_names.each do |attribute|
|
||||||
self.category = info['category']
|
next if attribute == 'name'
|
||||||
self.type = info['type']
|
value = info[attribute.to_sym]
|
||||||
self.rarity = info['rarity']
|
if value
|
||||||
self.rarity_index = info['rarity_index'].to_i
|
value = value.to_i if value.is_a? Float
|
||||||
self.price = info['price'].to_i
|
self[attribute] = value
|
||||||
self.weight_lbs = info['weight_lbs'].to_i
|
end
|
||||||
self.zones_restrict = info['zones_restrict']
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def pending_swf_assets
|
def pending_swf_assets
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@ class Item
|
||||||
end
|
end
|
||||||
|
|
||||||
def results
|
def results
|
||||||
@filters.map(&:to_query).inject(Item.all, &:merge).order(:name)
|
@filters.map(&:to_query).inject(Item.all, &:merge).
|
||||||
|
alphabetize_by_translations(Query.locale)
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
class AddTranslatedFieldsDirectlyToItems < ActiveRecord::Migration[7.1]
|
|
||||||
def change
|
|
||||||
add_column :items, :name, :string, null: false
|
|
||||||
add_column :items, :description, :text, null: false, default: ""
|
|
||||||
add_column :items, :rarity, :string, null: false, default: ""
|
|
||||||
|
|
||||||
reversible do |direction|
|
|
||||||
direction.up do
|
|
||||||
total_count = Item.count
|
|
||||||
saved_count = 0
|
|
||||||
Item.includes(:translations).find_in_batches do |items|
|
|
||||||
Item.transaction do
|
|
||||||
items.each do |item|
|
|
||||||
item.name = item.translation_for(:en).name
|
|
||||||
item.description = item.translation_for(:en).description || ""
|
|
||||||
item.rarity = item.translation_for(:en).rarity || ""
|
|
||||||
item.save!
|
|
||||||
end
|
|
||||||
saved_count += items.size
|
|
||||||
puts "Saved #{saved_count} of #{total_count} items"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -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.1].define(version: 2024_02_20_230420) do
|
ActiveRecord::Schema[7.1].define(version: 2024_02_03_161355) do
|
||||||
create_table "alt_styles", charset: "utf8mb4", collation: "utf8mb4_unicode_ci", force: :cascade do |t|
|
create_table "alt_styles", charset: "utf8mb4", collation: "utf8mb4_unicode_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
|
||||||
|
|
@ -144,9 +144,6 @@ ActiveRecord::Schema[7.1].define(version: 2024_02_20_230420) do
|
||||||
t.integer "manual_special_color_id"
|
t.integer "manual_special_color_id"
|
||||||
t.column "modeling_status_hint", "enum('done','glitchy')"
|
t.column "modeling_status_hint", "enum('done','glitchy')"
|
||||||
t.boolean "is_manually_nc", default: false, null: false
|
t.boolean "is_manually_nc", default: false, null: false
|
||||||
t.string "name", null: false
|
|
||||||
t.text "description", default: "", null: false
|
|
||||||
t.string "rarity", default: "", null: false
|
|
||||||
t.index ["modeling_status_hint", "created_at", "id"], name: "items_modeling_status_hint_and_created_at_and_id"
|
t.index ["modeling_status_hint", "created_at", "id"], name: "items_modeling_status_hint_and_created_at_and_id"
|
||||||
t.index ["modeling_status_hint", "created_at"], name: "items_modeling_status_hint_and_created_at"
|
t.index ["modeling_status_hint", "created_at"], name: "items_modeling_status_hint_and_created_at"
|
||||||
t.index ["modeling_status_hint", "id"], name: "items_modeling_status_hint_and_id"
|
t.index ["modeling_status_hint", "id"], name: "items_modeling_status_hint_and_id"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue