globalize3 for items

This commit is contained in:
Emi Matchu 2013-01-13 20:10:01 -06:00
parent 1439e4a74c
commit ef2423e87f
3 changed files with 60 additions and 19 deletions

View file

@ -10,13 +10,16 @@ class PetsController < ApplicationController
redirect_to roulette_path redirect_to roulette_path
else else
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.with_translations)
if user_signed_in? if user_signed_in?
points = current_user.contribute! @pet points = current_user.contribute! @pet
else else
@pet.save @pet.save
points = true points = true
end end
@pet.translate_items
respond_to do |format| respond_to do |format|
format.html do format.html do
path = destination + @pet.wardrobe_query path = destination + @pet.wardrobe_query

View file

@ -302,7 +302,7 @@ class Item < ActiveRecord::Base
end end
end end
def self.collection_from_pet_type_and_registries(pet_type, info_registry, asset_registry) def self.collection_from_pet_type_and_registries(pet_type, info_registry, asset_registry, scope=Item.scoped)
# bear in mind that registries are arrays with many nil elements, # bear in mind that registries are arrays with many nil elements,
# due to how the parser works # due to how the parser works
@ -317,7 +317,7 @@ class Item < ActiveRecord::Base
# Collect existing relationships # Collect existing relationships
existing_relationships_by_item_id_and_swf_asset_id = {} existing_relationships_by_item_id_and_swf_asset_id = {}
existing_items = Item.find_all_by_id(item_ids, :include => :parent_swf_asset_relationships) existing_items = scope.find_all_by_id(item_ids, :include => :parent_swf_asset_relationships)
existing_items.each do |item| existing_items.each do |item|
items[item.id] = item items[item.id] = item
relationships_by_swf_asset_id = {} relationships_by_swf_asset_id = {}

View file

@ -16,7 +16,13 @@ class Pet < ActiveRecord::Base
joins(:pet_type).where(PetType.arel_table[:id].in(color_ids)) joins(:pet_type).where(PetType.arel_table[:id].in(color_ids))
} }
def load! def load!(options={})
options[:item_scope] ||= Item.scoped
options[:locale] ||= I18n.default_locale
original_locale = I18n.locale
I18n.locale = options[:locale]
require 'ostruct' require 'ostruct'
begin begin
neopets_language_code = I18n.translate('neopets_language_code') neopets_language_code = I18n.translate('neopets_language_code')
@ -36,18 +42,27 @@ class Pet < ActiveRecord::Base
end end
contents = OpenStruct.new(envelope.messages[0].data.body) contents = OpenStruct.new(envelope.messages[0].data.body)
pet_data = OpenStruct.new(contents.custom_pet) pet_data = OpenStruct.new(contents.custom_pet)
self.pet_type = PetType.find_or_initialize_by_species_id_and_color_id(
pet_data.species_id.to_i, # in case this is running in a thread, explicitly grab an ActiveRecord
pet_data.color_id.to_i # connection, to avoid connection conflicts
) Pet.connection_pool.with_connection do
self.pet_type.body_id = pet_data.body_id self.pet_type = PetType.find_or_initialize_by_species_id_and_color_id(
self.pet_type.origin_pet = self pet_data.species_id.to_i,
biology = pet_data.biology_by_zone pet_data.color_id.to_i
biology[0] = nil # remove effects if present )
@pet_state = self.pet_type.add_pet_state_from_biology! biology self.pet_type.body_id = pet_data.body_id
@pet_state.label_by_pet(self, pet_data.owner) self.pet_type.origin_pet = self
@items = Item.collection_from_pet_type_and_registries(self.pet_type, biology = pet_data.biology_by_zone
contents.object_info_registry, contents.object_asset_registry) biology[0] = nil # remove effects if present
@pet_state = self.pet_type.add_pet_state_from_biology! biology
@pet_state.label_by_pet(self, pet_data.owner)
@items = Item.collection_from_pet_type_and_registries(self.pet_type,
contents.object_info_registry, contents.object_asset_registry,
options[:item_scope])
end
I18n.locale = original_locale
true true
end end
@ -74,7 +89,6 @@ class Pet < ActiveRecord::Base
{}.tap do |candidates| {}.tap do |candidates|
if @items if @items
@items.each do |item| @items.each do |item|
puts "#{item.name}: #{item.translations_needed}"
item.needed_translations.each do |locale| item.needed_translations.each do |locale|
candidates[locale] ||= [] candidates[locale] ||= []
candidates[locale] << item candidates[locale] << item
@ -83,6 +97,30 @@ class Pet < ActiveRecord::Base
end end
end end
end end
def translate_items
candidates = self.item_translation_candidates
until candidates.empty?
last_pet_loaded = nil
reloaded_pets = Parallel.map(candidates.keys, :in_threads => 8) do |locale|
Rails.logger.info "Reloading #{name} in #{locale}"
last_pet_loaded = Pet.load(name, :item_scope => Item.with_translations,
:locale => locale)
end
reloaded_pets.map(&:save!)
previous_candidates = candidates
candidates = last_pet_loaded.item_translation_candidates
if previous_candidates == candidates
# This condition should never happen if Neopets responds with correct
# data, but, if Neopets somehow responds with incorrect data, this
# condition could throw us into an infinite loop if uncaught. Better
# safe than sorry when working with external services.
raise "No change when reloading #{name} for #{candidates}"
end
end
end
before_validation do before_validation do
pet_type.save! pet_type.save!
@ -99,9 +137,9 @@ class Pet < ActiveRecord::Base
end end
end end
def self.load(name) def self.load(name, options={})
pet = Pet.find_or_initialize_by_name(name) pet = Pet.find_or_initialize_by_name(name)
pet.load! pet.load!(options)
pet pet
end end