Merge branch 'globalized_search' into i18n
Conflicts: Gemfile app/controllers/application_controller.rb app/controllers/items_controller.rb app/controllers/outfits_controller.rb app/helpers/application_helper.rb app/views/items/show.html.haml config/locales/en-MEEP.yml config/locales/en.yml public/stylesheets/compiled/screen.css
This commit is contained in:
commit
d3b449a8f9
107 changed files with 1557 additions and 650 deletions
9
Gemfile
9
Gemfile
|
@ -43,13 +43,20 @@ gem 'neopets', :git => 'git://github.com/matchu/neopets.git'
|
|||
|
||||
gem "mini_magick", "~> 3.4"
|
||||
|
||||
gem "fog", "~> 1.1.2"
|
||||
gem "fog", "~> 1.8.0"
|
||||
gem "carrierwave", "~> 0.5.8"
|
||||
|
||||
gem "parallel", "~> 0.5.17"
|
||||
|
||||
gem "http_accept_language", :git => "git://github.com/iain/http_accept_language.git"
|
||||
|
||||
gem "globalize3"
|
||||
|
||||
# My flex branch fixes a minor pagination bug. Once it's merged into the
|
||||
# original gem, we can switch back.
|
||||
gem "flex", :require => "flex/rails", :git => "git@github.com:matchu/flex.git"
|
||||
gem "patron", "~> 0.4.18"
|
||||
|
||||
group :development do
|
||||
gem "bullet", "~> 4.1.5"
|
||||
end
|
||||
|
|
104
Gemfile.lock
104
Gemfile.lock
|
@ -1,8 +1,8 @@
|
|||
GIT
|
||||
remote: git://github.com/eventmachine/eventmachine.git
|
||||
revision: 69151c3ebb3e4ecf2bb9b6e2fab2022dc34f8541
|
||||
revision: d7c8a14dc494193a775add4b16c1e303cab5b285
|
||||
specs:
|
||||
eventmachine (1.0.0.beta.4)
|
||||
eventmachine (1.0.0)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/iain/http_accept_language.git
|
||||
|
@ -12,9 +12,9 @@ GIT
|
|||
|
||||
GIT
|
||||
remote: git://github.com/igrigorik/em-http-request.git
|
||||
revision: ce50f322ce08d43a4a747cf333ea576765d764c4
|
||||
revision: 322f2273fa7ea07c1eeb92755bf67f1f05058e54
|
||||
specs:
|
||||
em-http-request (1.0.1)
|
||||
em-http-request (1.0.3)
|
||||
addressable (>= 2.2.3)
|
||||
cookiejar
|
||||
em-socksify
|
||||
|
@ -30,21 +30,21 @@ GIT
|
|||
|
||||
GIT
|
||||
remote: git://github.com/igrigorik/em-synchrony.git
|
||||
revision: c7209a58f9eb92e1dc81fb141297f9f257c2fdcb
|
||||
revision: fe592a4b9b5345bca329477cb8f2f8d186b6fc7f
|
||||
specs:
|
||||
em-synchrony (1.0.0)
|
||||
em-synchrony (1.0.2)
|
||||
eventmachine (>= 1.0.0.beta.1)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/matchu/neopets.git
|
||||
revision: fe694681a302243d2937e811355473f358035403
|
||||
revision: d33aaf63d4617d9236ef0d99452b3bdc577cbc8e
|
||||
specs:
|
||||
neopets (0.0.2)
|
||||
neopets (0.1.0)
|
||||
nokogiri (~> 1.5.2)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/oldmoe/mysqlplus.git
|
||||
revision: 3dbaa7c00ff0bb75ad9538cdef176c72de35d231
|
||||
revision: f07936d2eb9b0893994ed99fe82267b5e7770d06
|
||||
specs:
|
||||
mysqlplus (0.1.1)
|
||||
|
||||
|
@ -54,6 +54,15 @@ GIT
|
|||
specs:
|
||||
RocketAMF (1.0.0)
|
||||
|
||||
GIT
|
||||
remote: git@github.com:matchu/flex.git
|
||||
revision: d62f508f795ecdbb383f406865daa72368b43ba5
|
||||
specs:
|
||||
flex (0.4.1)
|
||||
multi_json (~> 1.3.4)
|
||||
progressbar (~> 0.11.0)
|
||||
prompter (~> 0.1.5)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
|
@ -88,17 +97,17 @@ GEM
|
|||
activemodel (= 3.0.19)
|
||||
activesupport (= 3.0.19)
|
||||
activesupport (3.0.19)
|
||||
addressable (2.2.6)
|
||||
addressable (2.3.2)
|
||||
arel (2.0.10)
|
||||
bcrypt-ruby (2.1.4)
|
||||
builder (2.1.2)
|
||||
bullet (4.1.5)
|
||||
bullet (4.1.6)
|
||||
uniform_notifier (~> 1.0.0)
|
||||
carrierwave (0.5.8)
|
||||
activesupport (~> 3.0)
|
||||
character-encodings (0.4.1)
|
||||
chronic (0.6.7)
|
||||
closure-compiler (1.1.4)
|
||||
closure-compiler (1.1.8)
|
||||
compass (0.10.6)
|
||||
haml (>= 3.0.4)
|
||||
cookiejar (0.3.0)
|
||||
|
@ -106,27 +115,32 @@ GEM
|
|||
bcrypt-ruby (~> 2.1.2)
|
||||
warden (~> 1.0.2)
|
||||
diff-lcs (1.1.3)
|
||||
em-socksify (0.1.0)
|
||||
eventmachine
|
||||
dye (0.1.4)
|
||||
em-socksify (0.2.1)
|
||||
eventmachine (>= 1.0.0.beta.4)
|
||||
erubis (2.6.6)
|
||||
abstract (>= 1.0.0)
|
||||
excon (0.9.6)
|
||||
factory_girl (2.3.2)
|
||||
activesupport
|
||||
factory_girl_rails (1.4.0)
|
||||
factory_girl (~> 2.3.0)
|
||||
excon (0.16.10)
|
||||
factory_girl (2.6.4)
|
||||
activesupport (>= 2.3.9)
|
||||
factory_girl_rails (1.7.0)
|
||||
factory_girl (~> 2.6.0)
|
||||
railties (>= 3.0.0)
|
||||
fog (1.1.2)
|
||||
fog (1.8.0)
|
||||
builder
|
||||
excon (~> 0.9.0)
|
||||
excon (~> 0.14)
|
||||
formatador (~> 0.2.0)
|
||||
mime-types
|
||||
multi_json (~> 1.0.3)
|
||||
multi_json (~> 1.0)
|
||||
net-scp (~> 1.0.4)
|
||||
net-ssh (>= 2.1.3)
|
||||
nokogiri (~> 1.5.0)
|
||||
ruby-hmac
|
||||
formatador (0.2.1)
|
||||
formatador (0.2.4)
|
||||
globalize3 (0.3.0)
|
||||
activemodel (>= 3.0.0)
|
||||
activerecord (>= 3.0.0)
|
||||
paper_trail (~> 2)
|
||||
haml (3.0.25)
|
||||
hoptoad_notifier (2.4.11)
|
||||
activesupport
|
||||
|
@ -146,20 +160,28 @@ GEM
|
|||
mime-types (1.19)
|
||||
mini_magick (3.4)
|
||||
subexec (~> 0.2.1)
|
||||
msgpack (0.4.6)
|
||||
multi_json (1.0.4)
|
||||
mysql2 (0.2.6)
|
||||
msgpack (0.4.7)
|
||||
multi_json (1.3.7)
|
||||
mysql2 (0.2.18)
|
||||
net-scp (1.0.4)
|
||||
net-ssh (>= 1.99.1)
|
||||
net-ssh (2.3.0)
|
||||
newrelic_rpm (3.5.3.25)
|
||||
nokogiri (1.5.3)
|
||||
net-ssh (2.6.3)
|
||||
newrelic_rpm (3.5.5.38)
|
||||
nokogiri (1.5.6)
|
||||
open4 (1.3.0)
|
||||
openneo-auth-signatory (0.1.0)
|
||||
ruby-hmac
|
||||
parallel (0.5.17)
|
||||
paper_trail (2.7.0)
|
||||
activerecord (~> 3.0)
|
||||
railties (~> 3.0)
|
||||
parallel (0.5.21)
|
||||
patron (0.4.18)
|
||||
polyglot (0.3.3)
|
||||
rack (1.2.6)
|
||||
progressbar (0.11.0)
|
||||
prompter (0.1.5)
|
||||
dye (>= 0.1.1)
|
||||
yard (>= 0.6.3)
|
||||
rack (1.2.7)
|
||||
rack-fiber_pool (0.9.2)
|
||||
rack-mount (0.6.14)
|
||||
rack (>= 1.0.0)
|
||||
|
@ -183,9 +205,9 @@ GEM
|
|||
rdiscount (1.6.8)
|
||||
rdoc (3.12)
|
||||
json (~> 1.4)
|
||||
redis (2.2.2)
|
||||
redis-namespace (1.1.0)
|
||||
redis (< 3.0.0)
|
||||
redis (3.0.2)
|
||||
redis-namespace (1.2.1)
|
||||
redis (~> 3.0.0)
|
||||
resque (1.15.0)
|
||||
json (~> 1.4.6)
|
||||
redis-namespace (>= 0.10.0)
|
||||
|
@ -214,14 +236,14 @@ GEM
|
|||
rspec-rails (2.0.1)
|
||||
rspec (~> 2.0.0)
|
||||
ruby-hmac (0.4.0)
|
||||
rufus-scheduler (2.0.16)
|
||||
rufus-scheduler (2.0.17)
|
||||
tzinfo (>= 0.3.23)
|
||||
sanitize (2.0.3)
|
||||
nokogiri (>= 1.4.4, < 1.6)
|
||||
sinatra (1.2.8)
|
||||
rack (~> 1.1)
|
||||
tilt (>= 1.2.2, < 2.0)
|
||||
subexec (0.2.1)
|
||||
subexec (0.2.2)
|
||||
swf_converter (0.0.3)
|
||||
thor (0.14.6)
|
||||
tilt (1.3.3)
|
||||
|
@ -230,14 +252,15 @@ GEM
|
|||
polyglot (>= 0.3.1)
|
||||
tzinfo (0.3.35)
|
||||
uniform_notifier (1.0.2)
|
||||
vegas (0.1.8)
|
||||
vegas (0.1.11)
|
||||
rack (>= 1.0.0)
|
||||
warden (1.0.6)
|
||||
rack (>= 1.0)
|
||||
whenever (0.7.3)
|
||||
activesupport (>= 2.3.4)
|
||||
chronic (~> 0.6.3)
|
||||
will_paginate (3.0.2)
|
||||
will_paginate (3.0.4)
|
||||
yard (0.8.3)
|
||||
yui-compressor (0.9.6)
|
||||
POpen4 (>= 0.1.4)
|
||||
|
||||
|
@ -257,7 +280,9 @@ DEPENDENCIES
|
|||
em-synchrony!
|
||||
eventmachine!
|
||||
factory_girl_rails (~> 1.0)
|
||||
fog (~> 1.1.2)
|
||||
flex!
|
||||
fog (~> 1.8.0)
|
||||
globalize3
|
||||
haml (~> 3.0.18)
|
||||
hoptoad_notifier
|
||||
http_accept_language!
|
||||
|
@ -272,6 +297,7 @@ DEPENDENCIES
|
|||
nokogiri (~> 1.5.2)
|
||||
openneo-auth-signatory (~> 0.1.0)
|
||||
parallel (~> 0.5.17)
|
||||
patron (~> 0.4.18)
|
||||
rack-fiber_pool
|
||||
rails (= 3.0.19)
|
||||
rdiscount (~> 1.6.5)
|
||||
|
|
|
@ -57,7 +57,7 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def valid_locale?(locale)
|
||||
locale && I18n.available_locales.include?(locale.to_sym)
|
||||
locale && I18n.usable_locales.include?(locale.to_sym)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -188,15 +188,17 @@ class ClosetHangersController < ApplicationController
|
|||
|
||||
def find_closet_lists_by_owned(closet_lists)
|
||||
return {} if closet_lists == []
|
||||
closet_lists.alphabetical.includes(:hangers => :item).
|
||||
closet_lists.alphabetical.includes(:hangers => {:item => :translations}).
|
||||
group_by(&:hangers_owned)
|
||||
end
|
||||
|
||||
def find_unlisted_closet_hangers_by_owned(visible_groups)
|
||||
unless visible_groups.empty?
|
||||
@user.closet_hangers.unlisted.
|
||||
owned_before_wanted.alphabetical_by_item_name.includes(:item).
|
||||
where(:owned => [visible_groups]).group_by(&:owned)
|
||||
owned_before_wanted.alphabetical_by_item_name.
|
||||
includes(:item => :translations).
|
||||
where(:owned => [visible_groups]).
|
||||
group_by(&:owned)
|
||||
else
|
||||
{}
|
||||
end
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
class ItemZoneSetsController < ApplicationController
|
||||
caches_page :index
|
||||
|
||||
def index
|
||||
render :json => Zone::ItemZoneSets.keys.sort.as_json
|
||||
render :json => Zone.all_plain_labels
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class ItemsController < ApplicationController
|
||||
before_filter :set_query
|
||||
rescue_from Item::Search::Error, :with => :search_error
|
||||
|
||||
def index
|
||||
if params.has_key?(:q)
|
||||
|
@ -8,25 +9,21 @@ class ItemsController < ApplicationController
|
|||
per_page = params[:per_page].to_i
|
||||
per_page = 50 if per_page && per_page > 50
|
||||
else
|
||||
per_page = nil
|
||||
per_page = 30
|
||||
end
|
||||
@items = Item.search(@query, current_user).alphabetize.paginate :page => params[:page], :per_page => per_page
|
||||
# Note that we sort by name by hand, since we might have to use
|
||||
# fallbacks after the fact
|
||||
@items = Item::Search::Query.from_text(@query, current_user).
|
||||
paginate(:page => params[:page], :per_page => per_page)
|
||||
assign_closeted!
|
||||
respond_to do |format|
|
||||
format.html { render }
|
||||
format.json { render :json => {:items => @items, :total_pages => @items.total_pages} }
|
||||
format.js { render :json => {:items => @items, :total_pages => @items.total_pages}, :callback => params[:callback] }
|
||||
end
|
||||
rescue Item::SearchError
|
||||
@items = []
|
||||
respond_to do |format|
|
||||
format.html { flash.now[:alert] = $!.message }
|
||||
format.json { render :json => {:error => $!.message} }
|
||||
format.js { render :json => {:error => $!.message}, :callback => params[:callback] }
|
||||
end
|
||||
end
|
||||
elsif params.has_key?(:ids) && params[:ids].is_a?(Array)
|
||||
@items = Item.find(params[:ids])
|
||||
@items = Item.includes(:translations).find(params[:ids])
|
||||
assign_closeted!
|
||||
respond_to do |format|
|
||||
format.json { render :json => @items }
|
||||
|
@ -35,7 +32,7 @@ class ItemsController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.html {
|
||||
unless localized_fragment_exist?('items#index newest_items')
|
||||
@newest_items = Item.newest.limit(18)
|
||||
@newest_items = Item.newest.includes(:translations).limit(18)
|
||||
end
|
||||
}
|
||||
format.js { render :json => {:error => '$q required'}}
|
||||
|
@ -48,6 +45,15 @@ class ItemsController < ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
unless localized_fragment_exist?("items/#{@item.id} info")
|
||||
@occupied_zones = @item.occupied_zones(
|
||||
:scope => Zone.includes_translations.alphabetical
|
||||
)
|
||||
@restricted_zones = @item.restricted_zones(
|
||||
:scope => Zone.includes_translations.alphabetical
|
||||
)
|
||||
end
|
||||
|
||||
unless localized_fragment_exist?("items/#{@item.id} contributors")
|
||||
@contributors_with_counts = @item.contributors_with_counts
|
||||
end
|
||||
|
@ -96,7 +102,8 @@ class ItemsController < ApplicationController
|
|||
raise ActiveRecord::RecordNotFound, 'Pet type not found'
|
||||
end
|
||||
|
||||
@items = @pet_type.needed_items.alphabetize
|
||||
@items = @pet_type.needed_items.includes(:translations).
|
||||
alphabetize_by_translations
|
||||
assign_closeted!
|
||||
|
||||
respond_to do |format|
|
||||
|
@ -111,6 +118,16 @@ class ItemsController < ApplicationController
|
|||
current_user.assign_closeted_to_items!(@items) if user_signed_in?
|
||||
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
|
||||
|
||||
def set_query
|
||||
@query = params[:q]
|
||||
end
|
||||
|
|
|
@ -42,12 +42,13 @@ class OutfitsController < ApplicationController
|
|||
|
||||
def new
|
||||
unless localized_fragment_exist?(:action_suffix => 'start_from_scratch_form_content')
|
||||
@colors = Color.all_ordered_by_name
|
||||
@species = Species.all_ordered_by_name
|
||||
@colors = Color.alphabetical
|
||||
@species = Species.alphabetical
|
||||
end
|
||||
|
||||
unless localized_fragment_exist?('outfits#new newest_items')
|
||||
@newest_items = Item.newest.select([:id, :name, :thumbnail_url]).limit(9)
|
||||
@newest_items = Item.newest.select([:id, :name, :thumbnail_url]).
|
||||
includes(:translations).limit(9)
|
||||
end
|
||||
|
||||
unless localized_fragment_exist?('outfits#new latest_contribution')
|
||||
|
@ -65,8 +66,13 @@ class OutfitsController < ApplicationController
|
|||
end
|
||||
|
||||
def start
|
||||
# Start URLs are always in English, so let's make sure we search in
|
||||
# English.
|
||||
I18n.locale = I18n.default_locale
|
||||
|
||||
@species = Species.find_by_name params[:species_name]
|
||||
@color = Color.find_by_name params[:color_name]
|
||||
|
||||
if @species && @color
|
||||
redirect_to wardrobe_path(:species => @species.id, :color => @color.id)
|
||||
else
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
class PetAttributesController < ApplicationController
|
||||
caches_page :index
|
||||
|
||||
def index
|
||||
render :json => {
|
||||
:color => Color.all_ordered_by_name,
|
||||
:species => Species.all_ordered_by_name
|
||||
:color => Color.alphabetical,
|
||||
:species => Species.alphabetical
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,13 +10,16 @@ class PetsController < ApplicationController
|
|||
redirect_to roulette_path
|
||||
else
|
||||
raise Pet::PetNotFound unless params[:name]
|
||||
@pet = Pet.load(params[:name])
|
||||
@pet = Pet.load(params[:name], :item_scope => Item.includes(:translations))
|
||||
if user_signed_in?
|
||||
points = current_user.contribute! @pet
|
||||
else
|
||||
@pet.save
|
||||
points = true
|
||||
end
|
||||
|
||||
@pet.translate_items
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
path = destination + @pet.wardrobe_query
|
||||
|
|
|
@ -3,7 +3,7 @@ class SitemapController < ApplicationController
|
|||
|
||||
def index
|
||||
respond_to do |format|
|
||||
format.xml { @items = Item.sitemap }
|
||||
format.xml { @items = Item.includes(:translations).sitemap }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@ class SwfAssetsController < ApplicationController
|
|||
def index
|
||||
if params[:item_id]
|
||||
item = Item.find(params[:item_id])
|
||||
@swf_assets = item.swf_assets
|
||||
@swf_assets = item.swf_assets.includes_depth
|
||||
if params[:body_id]
|
||||
@swf_assets = @swf_assets.fitting_body_id(params[:body_id])
|
||||
else
|
||||
|
@ -15,33 +15,32 @@ class SwfAssetsController < ApplicationController
|
|||
end
|
||||
elsif params[:pet_type_id] && params[:item_ids]
|
||||
pet_type = PetType.find(params[:pet_type_id], :select => [:body_id, :species_id])
|
||||
items = Item.find(params[:item_ids], :select => [:id, :species_support_ids])
|
||||
compatible_items = items.select { |i| i.support_species?(pet_type.species) }
|
||||
compatible_item_ids = compatible_items.map(&:id)
|
||||
|
||||
@swf_assets = SwfAsset.object_assets.
|
||||
@swf_assets = SwfAsset.object_assets.includes_depth.
|
||||
fitting_body_id(pet_type.body_id).
|
||||
for_item_ids(compatible_item_ids).
|
||||
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.all
|
||||
@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
|
||||
@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.biology_assets.where(:remote_id => params[:ids][:biology]).all
|
||||
@swf_assets += SwfAsset.includes_depth.biology_assets.where(:remote_id => params[:ids][:biology]).all
|
||||
end
|
||||
if params[:ids][:object]
|
||||
@swf_assets += SwfAsset.object_assets.where(:remote_id => params[:ids][:object]).all
|
||||
@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.object_assets.
|
||||
@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])
|
||||
|
|
18
app/flex/flex_search.rb
Normal file
18
app/flex/flex_search.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
# inspect the methods loaded in this module and their usage
|
||||
# in the rails console by just typing:
|
||||
# >> puts FlexSearch.flex.info
|
||||
# you can eventually restrict the info to a single method by pasing its name:
|
||||
# >> puts FlexSearch.flex.info :search
|
||||
# see the detailed doc for this feature at https://github.com/ddnexus/flex/wiki/Selfdoc
|
||||
|
||||
module FlexSearch
|
||||
|
||||
extend self
|
||||
|
||||
include Flex::Loader
|
||||
flex.load_search_source
|
||||
|
||||
# you may need to add more method here, usually wrapper methods
|
||||
# that use one of the autogenerated methods from the loaded templates
|
||||
|
||||
end
|
83
app/flex/flex_search.yml
Normal file
83
app/flex/flex_search.yml
Normal file
|
@ -0,0 +1,83 @@
|
|||
# Add here your search queries
|
||||
# see the detailed Source documentation at https://github.com/ddnexus/flex/wiki/Sources
|
||||
|
||||
|
||||
# ANCHORS litheral key: it will not be used as template
|
||||
# you can store here fragments of queries to reuse in the templates below
|
||||
ANCHORS:
|
||||
- &name_partial
|
||||
multi_match:
|
||||
query: <<name>>
|
||||
fields: <<fields>>
|
||||
type: phrase
|
||||
- &species_support_id_partial
|
||||
term:
|
||||
species_support_id: <<species_support_id>>
|
||||
- &occupied_zone_id_partial
|
||||
terms:
|
||||
occupied_zone_id: <<occupied_zone_id>>
|
||||
- &restricted_zone_id_partial
|
||||
terms:
|
||||
restricted_zone_id: <<restricted_zone_id>>
|
||||
- &user_closet_hangers_ownership_partial
|
||||
has_child:
|
||||
type: closet_hanger
|
||||
query:
|
||||
bool:
|
||||
must:
|
||||
- term:
|
||||
user_id: <<user_id>>
|
||||
- term:
|
||||
owned: <<user_closet_hanger_ownership>>
|
||||
|
||||
_names:
|
||||
*name_partial
|
||||
|
||||
_negative_names:
|
||||
*name_partial
|
||||
|
||||
_species_support_ids:
|
||||
*species_support_id_partial
|
||||
|
||||
_negative_species_support_ids:
|
||||
*species_support_id_partial
|
||||
|
||||
_occupied_zone_ids:
|
||||
*occupied_zone_id_partial
|
||||
|
||||
_negative_occupied_zone_ids:
|
||||
*occupied_zone_id_partial
|
||||
|
||||
_restricted_zone_ids:
|
||||
*restricted_zone_id_partial
|
||||
|
||||
_negative_restricted_zone_ids:
|
||||
*restricted_zone_id_partial
|
||||
|
||||
_user_closet_hanger_ownerships:
|
||||
*user_closet_hangers_ownership_partial
|
||||
|
||||
_negative_user_closet_hanger_ownerships:
|
||||
*user_closet_hangers_ownership_partial
|
||||
|
||||
item_search:
|
||||
- query:
|
||||
bool:
|
||||
must:
|
||||
- term:
|
||||
is_nc: <<is_nc= ~>>
|
||||
- term:
|
||||
is_pb: <<is_pb= ~>>
|
||||
- <<_names= ~>>
|
||||
- <<_species_support_ids= ~>>
|
||||
- <<_occupied_zone_ids= ~>>
|
||||
- <<_restricted_zone_ids= ~>>
|
||||
- <<_user_closet_hanger_ownerships= ~>>
|
||||
must_not:
|
||||
- <<_negative_names= ~>>
|
||||
- <<_negative_species_support_ids= ~>>
|
||||
- <<_negative_occupied_zone_ids= ~>>
|
||||
- <<_negative_restricted_zone_ids= ~>>
|
||||
- <<_negative_user_closet_hanger_ownerships= ~>>
|
||||
sort:
|
||||
- name.<<locale>>.untouched
|
36
app/flex/flex_search_extender.rb
Normal file
36
app/flex/flex_search_extender.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
# see the detailed Extenders documentation at https://github.com/ddnexus/flex/wiki/Extenders
|
||||
|
||||
module FlexSearchExtender
|
||||
|
||||
# set this method to restrict this extender to certain types of results
|
||||
# see the other Flex extenders for reference (https://github.com/ddnexus/flex/tree/master/lib/flex/result)
|
||||
def self.should_extend?(response)
|
||||
true
|
||||
end
|
||||
|
||||
def scoped_loaded_collection(options)
|
||||
options[:scopes] ||= {}
|
||||
@loaded_collection ||= begin
|
||||
records = []
|
||||
# returns a structure like {Comment=>[{"_id"=>"123", ...}, {...}], BlogPost=>[...]}
|
||||
h = Flex::Utils.group_array_by(collection) do |d|
|
||||
d.mapped_class(should_raise=true)
|
||||
end
|
||||
h.each do |klass, docs|
|
||||
scope = options[:scopes][klass.name] || klass.scoped
|
||||
records |= scope.find(docs.map(&:_id))
|
||||
end
|
||||
class_ids = collection.map { |d| [d.mapped_class.to_s, d._id] }
|
||||
# Reorder records to preserve order from search results
|
||||
records = class_ids.map do |class_str, id|
|
||||
records.detect do |record|
|
||||
record.class.to_s == class_str && record.id.to_s == id.to_s
|
||||
end
|
||||
end
|
||||
records.extend Flex::Result::Collection
|
||||
records.setup(self['hits']['total'], variables)
|
||||
records
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -43,7 +43,10 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def canonical_path(resource)
|
||||
original_locale = I18n.locale
|
||||
I18n.locale = I18n.default_locale
|
||||
content_for :meta, tag(:link, :rel => 'canonical', :href => url_for(resource))
|
||||
I18n.locale = original_locale
|
||||
end
|
||||
|
||||
def contact_email
|
||||
|
@ -100,9 +103,18 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def locale_options
|
||||
I18n.available_locales.map do |available_locale|
|
||||
current_locale_is_public = false
|
||||
options = I18n.public_locales.map do |available_locale|
|
||||
current_locale_is_public = true if I18n.locale == available_locale
|
||||
[translate('locale_name', :locale => available_locale), available_locale]
|
||||
end
|
||||
|
||||
unless current_locale_is_public
|
||||
name = translate('locale_name', :locale => I18n.locale) + ' (alpha)'
|
||||
options << [name, I18n.locale]
|
||||
end
|
||||
|
||||
options
|
||||
end
|
||||
|
||||
def localized_cache(key={}, &block)
|
||||
|
|
|
@ -20,7 +20,7 @@ module ItemsHelper
|
|||
end
|
||||
|
||||
def standard_species_search_links
|
||||
build_on_pet_types(Species.all) do |pet_type|
|
||||
build_on_pet_types(Species.alphabetical) do |pet_type|
|
||||
image = pet_type_image(pet_type, :happy, :zoom)
|
||||
query = "species:#{pet_type.species.name}"
|
||||
link_to(image, items_path(:q => query))
|
||||
|
@ -73,7 +73,7 @@ module ItemsHelper
|
|||
end
|
||||
|
||||
def list_zones(zones, method=:label)
|
||||
zones.sort { |x,y| x.label <=> y.label }.map(&method).join(', ')
|
||||
zones.map(&method).join(', ')
|
||||
end
|
||||
|
||||
def nc_icon
|
||||
|
@ -125,7 +125,8 @@ module ItemsHelper
|
|||
def build_on_pet_types(species, special_color=nil, &block)
|
||||
species_ids = species.map(&:id)
|
||||
pet_types = special_color ?
|
||||
PetType.where(:color_id => special_color.id, :species_id => species_ids).order(:species_id) :
|
||||
PetType.where(:color_id => special_color.id, :species_id => species_ids).
|
||||
order(:species_id).includes_child_translations :
|
||||
PetType.random_basic_per_species(species.map(&:id))
|
||||
pet_types.map(&block).join.html_safe
|
||||
end
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class ClosetHanger < ActiveRecord::Base
|
||||
include Flex::Model
|
||||
|
||||
belongs_to :item
|
||||
belongs_to :list, :class_name => 'ClosetList'
|
||||
belongs_to :user
|
||||
|
@ -30,6 +32,17 @@ class ClosetHanger < ActiveRecord::Base
|
|||
|
||||
before_validation :merge_quantities, :set_owned_by_list
|
||||
|
||||
flex.parent :item, 'item' => 'closet_hanger'
|
||||
flex.sync self
|
||||
|
||||
def flex_source
|
||||
{
|
||||
:user_id => user_id,
|
||||
:item_id => item_id,
|
||||
:owned => owned?
|
||||
}.to_json
|
||||
end
|
||||
|
||||
def verb(subject=:someone)
|
||||
self.class.verb(subject, owned?)
|
||||
end
|
||||
|
@ -56,23 +69,28 @@ class ClosetHanger < ActiveRecord::Base
|
|||
end
|
||||
|
||||
hanger = self.where(conditions).first
|
||||
unless hanger
|
||||
hanger = self.new
|
||||
hanger.user_id = conditions[:user_id]
|
||||
hanger.item_id = conditions[:item_id]
|
||||
# One of the following will be nil, and that's okay. If owned is nil,
|
||||
# we'll cover for it before validation, as always.
|
||||
hanger.owned = conditions[:owned]
|
||||
hanger.list_id = conditions[:list_id]
|
||||
end
|
||||
|
||||
unless quantity == 0
|
||||
Rails.logger.debug("Logging to #{hanger.id} quantity #{quantity}")
|
||||
if quantity > 0
|
||||
# If quantity is non-zero, create/update the corresponding hanger.
|
||||
|
||||
unless hanger
|
||||
hanger = self.new
|
||||
hanger.user_id = conditions[:user_id]
|
||||
hanger.item_id = conditions[:item_id]
|
||||
# One of the following will be nil, and that's okay. If owned is nil,
|
||||
# we'll cover for it before validation, as always.
|
||||
hanger.owned = conditions[:owned]
|
||||
hanger.list_id = conditions[:list_id]
|
||||
end
|
||||
|
||||
hanger.quantity = quantity
|
||||
hanger.save!
|
||||
else
|
||||
hanger.destroy if hanger
|
||||
elsif hanger
|
||||
# If quantity is zero and there's a hanger, destroy it.
|
||||
hanger.destroy
|
||||
end
|
||||
|
||||
# If quantity is zero and there's no hanger, good. Do nothing.
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
class Color < PetAttribute
|
||||
fetch_objects!
|
||||
class Color < ActiveRecord::Base
|
||||
translates :name
|
||||
|
||||
Basic = %w(blue green red yellow).map { |name| find_by_name(name) }
|
||||
BasicIds = Basic.map(&:id)
|
||||
scope :alphabetical, lambda { includes(:translations).order(Color::Translation.arel_table[:name]) }
|
||||
scope :basic, where(:basic => true)
|
||||
scope :standard, where(:standard => true)
|
||||
scope :nonstandard, where(:standard => false)
|
||||
|
||||
def self.basic_ids
|
||||
BasicIds
|
||||
def as_json(options={})
|
||||
{:id => id, :name => human_name}
|
||||
end
|
||||
|
||||
def self.nonstandard_ids
|
||||
@nonstandard_ids ||= File.read(Rails.root.join('config', 'nonstandard_colors.txt')).
|
||||
chomp.split("\n").map { |name| Color.find_by_name(name).id }
|
||||
def human_name
|
||||
name.split(' ').map { |word| word.capitalize }.join(' ')
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
class Item < ActiveRecord::Base
|
||||
include Flex::Model
|
||||
include PrettyParam
|
||||
|
||||
set_inheritance_column 'inheritance_type' # PHP Impress used "type" to describe category
|
||||
|
||||
SwfAssetType = 'object'
|
||||
|
||||
translates :name, :description, :rarity
|
||||
|
||||
has_many :closet_hangers
|
||||
has_one :contribution, :as => :contributed
|
||||
has_many :parent_swf_asset_relationships, :as => :parent
|
||||
|
@ -15,18 +20,16 @@ class Item < ActiveRecord::Base
|
|||
SPECIAL_COLOR_DESCRIPTION_REGEX =
|
||||
/This item is only wearable by Neopets painted ([a-zA-Z]+)\.|WARNING: This [a-zA-Z]+ can be worn by ([a-zA-Z]+) [a-zA-Z]+ ONLY!/
|
||||
|
||||
SPECIAL_PAINTBRUSH_COLORS_PATH = Rails.root.join('config', 'colors_with_unique_bodies.txt')
|
||||
SPECIAL_PAINTBRUSH_COLORS = File.read(SPECIAL_PAINTBRUSH_COLORS_PATH).split("\n").map { |name| Color.find_by_name(name) }
|
||||
|
||||
set_table_name 'objects' # Neo & PHP Impress call them objects, but the class name is a conflict (duh!)
|
||||
set_inheritance_column 'inheritance_type' # PHP Impress used "type" to describe category
|
||||
|
||||
cattr_reader :per_page
|
||||
@@per_page = 30
|
||||
|
||||
scope :alphabetize, order('name ASC')
|
||||
scope :alphabetize, order(arel_table[:name])
|
||||
scope :alphabetize_by_translations, lambda {
|
||||
it = Item::Translation.arel_table
|
||||
order(it[:name])
|
||||
}
|
||||
|
||||
scope :join_swf_assets, joins(:swf_assets).group('objects.id')
|
||||
scope :join_swf_assets, joins(:swf_assets).group(arel_table[:id])
|
||||
|
||||
scope :newest, order(arel_table[:created_at].desc) if arel_table[:created_at]
|
||||
|
||||
|
@ -35,10 +38,32 @@ class Item < ActiveRecord::Base
|
|||
scope :sold_in_mall, where(:sold_in_mall => true)
|
||||
scope :not_sold_in_mall, where(:sold_in_mall => false)
|
||||
|
||||
scope :sitemap, select([:id, :name]).order(:id).limit(49999)
|
||||
scope :sitemap, select([arel_table[:id], arel_table[:name]]).
|
||||
order(arel_table[:id]).limit(49999)
|
||||
|
||||
scope :with_closet_hangers, joins(:closet_hangers)
|
||||
|
||||
flex.sync self
|
||||
|
||||
def flex_source
|
||||
indexed_attributes = {
|
||||
:is_nc => self.nc?,
|
||||
:is_pb => self.pb?,
|
||||
:species_support_id => self.species_support_ids,
|
||||
:occupied_zone_id => self.occupied_zone_ids,
|
||||
:restricted_zone_id => self.restricted_zone_ids,
|
||||
:name => {}
|
||||
}
|
||||
|
||||
I18n.usable_locales_with_neopets_language_code.each do |locale|
|
||||
I18n.with_locale(locale) do
|
||||
indexed_attributes[:name][locale] = self.name
|
||||
end
|
||||
end
|
||||
|
||||
indexed_attributes.to_json
|
||||
end
|
||||
|
||||
def closeted?
|
||||
@owned || @wanted
|
||||
end
|
||||
|
@ -73,6 +98,10 @@ class Item < ActiveRecord::Base
|
|||
NCRarities.include?(rarity_index)
|
||||
end
|
||||
|
||||
def pb?
|
||||
(self.description == PAINTBRUSH_SET_DESCRIPTION)
|
||||
end
|
||||
|
||||
def owned?
|
||||
@owned
|
||||
end
|
||||
|
@ -81,17 +110,27 @@ class Item < ActiveRecord::Base
|
|||
@wanted
|
||||
end
|
||||
|
||||
def restricted_zones
|
||||
unless @restricted_zones
|
||||
@restricted_zones = []
|
||||
zones_restrict.split(//).each_with_index do |switch, id|
|
||||
@restricted_zones << Zone.find(id.to_i + 1) if switch == '1'
|
||||
end
|
||||
end
|
||||
@restricted_zones
|
||||
def restricted_zones(options={})
|
||||
options[:scope] ||= Zone.scoped
|
||||
options[:scope].find(restricted_zone_ids)
|
||||
end
|
||||
|
||||
def occupied_zones
|
||||
def restricted_zone_ids
|
||||
unless @restricted_zone_ids
|
||||
@restricted_zone_ids = []
|
||||
zones_restrict.split(//).each_with_index do |switch, id|
|
||||
@restricted_zone_ids << (id.to_i + 1) if switch == '1'
|
||||
end
|
||||
end
|
||||
@restricted_zone_ids
|
||||
end
|
||||
|
||||
def occupied_zone_ids
|
||||
occupied_zones.map(&:id)
|
||||
end
|
||||
|
||||
def occupied_zones(options={})
|
||||
options[:scope] ||= Zone.scoped
|
||||
all_body_ids = []
|
||||
zone_body_ids = {}
|
||||
selected_assets = swf_assets.select('body_id, zone_id').each do |swf_asset|
|
||||
|
@ -100,12 +139,11 @@ class Item < ActiveRecord::Base
|
|||
body_ids << swf_asset.body_id unless body_ids.include?(swf_asset.body_id)
|
||||
all_body_ids << swf_asset.body_id unless all_body_ids.include?(swf_asset.body_id)
|
||||
end
|
||||
zones = []
|
||||
zones = options[:scope].find(zone_body_ids.keys)
|
||||
zones_by_id = zones.inject({}) { |h, z| h[z.id] = z; h }
|
||||
total_body_ids = all_body_ids.size
|
||||
zone_body_ids.each do |zone_id, body_ids|
|
||||
zone = Zone.find(zone_id)
|
||||
zone.sometimes = true if body_ids.size < total_body_ids
|
||||
zones << zone
|
||||
zones_by_id[zone_id].sometimes = true if body_ids.size < total_body_ids
|
||||
end
|
||||
zones
|
||||
end
|
||||
|
@ -120,17 +158,21 @@ class Item < ActiveRecord::Base
|
|||
|
||||
protected
|
||||
def determine_special_color
|
||||
if description.include?(PAINTBRUSH_SET_DESCRIPTION)
|
||||
downcased_name = name.downcase
|
||||
SPECIAL_PAINTBRUSH_COLORS.each do |color|
|
||||
return color if downcased_name.include?(color.name)
|
||||
I18n.with_locale(I18n.default_locale) do
|
||||
# Rather than go find the special description in all locales, let's just
|
||||
# run this logic in English.
|
||||
if description.include?(PAINTBRUSH_SET_DESCRIPTION)
|
||||
downcased_name = name.downcase
|
||||
Color.nonstandard.each do |color|
|
||||
return color if downcased_name.include?(color.name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
match = description.match(SPECIAL_COLOR_DESCRIPTION_REGEX)
|
||||
if match
|
||||
color = match[1] || match[2]
|
||||
return Color.find_by_name(color.downcase)
|
||||
match = description.match(SPECIAL_COLOR_DESCRIPTION_REGEX)
|
||||
if match
|
||||
color = match[1] || match[2]
|
||||
return Color.find_by_name(color.downcase)
|
||||
end
|
||||
end
|
||||
end
|
||||
public
|
||||
|
@ -146,45 +188,18 @@ class Item < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def supported_species
|
||||
@supported_species ||= species_support_ids.blank? ? Species.all : species_support_ids.sort.map { |id| Species.find(id) }
|
||||
body_ids = swf_assets.select([:body_id]).map(&:body_id)
|
||||
return Species.all if body_ids.include?(0)
|
||||
|
||||
pet_types = PetType.where(:body_id => body_ids).select([:species_id])
|
||||
species_ids = pet_types.map(&:species_id).uniq
|
||||
Species.find(species_ids)
|
||||
end
|
||||
|
||||
def support_species?(species)
|
||||
species_support_ids.blank? || species_support_ids.include?(species.id)
|
||||
end
|
||||
|
||||
def self.search(query, user=nil)
|
||||
raise SearchError, "Please provide a search query" unless query
|
||||
query = query.strip
|
||||
raise SearchError, "Search queries should be at least 3 characters" if query.length < 3
|
||||
query_conditions = [Condition.new]
|
||||
in_phrase = false
|
||||
query.each_char do |c|
|
||||
if c == ' ' && !in_phrase
|
||||
query_conditions << Condition.new
|
||||
elsif c == '"'
|
||||
in_phrase = !in_phrase
|
||||
elsif c == ':' && !in_phrase
|
||||
query_conditions.last.to_filter!
|
||||
elsif c == '-' && !in_phrase && query_conditions.last.empty?
|
||||
query_conditions.last.negate!
|
||||
else
|
||||
query_conditions.last << c
|
||||
end
|
||||
end
|
||||
limited_filters_used = []
|
||||
query_conditions.inject(self.scoped) do |scope, condition|
|
||||
if condition.filter? && LimitedSearchFilters.include?(condition.filter)
|
||||
if limited_filters_used.include?(condition.filter)
|
||||
raise SearchError, "The #{condition.filter} filter is complex; please only use one per search. Thanks!"
|
||||
else
|
||||
limited_filters_used << condition.filter
|
||||
end
|
||||
end
|
||||
condition.narrow(scope, user)
|
||||
end
|
||||
end
|
||||
|
||||
def as_json(options = {})
|
||||
{
|
||||
:description => description,
|
||||
|
@ -231,6 +246,12 @@ class Item < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def body_specific?
|
||||
# If there are species support IDs (it's not empty), the item is
|
||||
# body-specific. If it's empty, it fits everyone the same.
|
||||
!species_support_ids.empty?
|
||||
end
|
||||
|
||||
def origin_registry_info=(info)
|
||||
# bear in mind that numbers from registries are floats
|
||||
self.species_support_ids = info[:species_support].map(&:to_i)
|
||||
|
@ -253,6 +274,12 @@ class Item < ActiveRecord::Base
|
|||
@parent_swf_asset_relationships_to_update = rels
|
||||
end
|
||||
|
||||
def needed_translations
|
||||
translatable_locales = Set.new(I18n.locales_with_neopets_language_code)
|
||||
translated_locales = Set.new(translations.map(&:locale))
|
||||
translatable_locales - translated_locales
|
||||
end
|
||||
|
||||
def self.all_by_ids_or_children(ids, swf_assets)
|
||||
swf_asset_ids = []
|
||||
swf_assets_by_id = {}
|
||||
|
@ -284,7 +311,7 @@ class Item < ActiveRecord::Base
|
|||
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,
|
||||
# due to how the parser works
|
||||
|
||||
|
@ -299,7 +326,7 @@ class Item < ActiveRecord::Base
|
|||
|
||||
# Collect existing relationships
|
||||
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|
|
||||
items[item.id] = item
|
||||
relationships_by_swf_asset_id = {}
|
||||
|
@ -656,214 +683,4 @@ class Item < ActiveRecord::Base
|
|||
class SpiderHTTPError < SpiderError;end
|
||||
class SpiderJSONError < SpiderError;end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
SearchFilterScopes = []
|
||||
LimitedSearchFilters = []
|
||||
|
||||
def self.search_filter(name, options={}, &block)
|
||||
assume_complement = options.delete(:assume_complement) || true
|
||||
name = name.to_s
|
||||
SearchFilterScopes << name
|
||||
LimitedSearchFilters << name if options[:limit]
|
||||
|
||||
(class << self; self; end).instance_eval do
|
||||
if options[:full]
|
||||
define_method "search_filter_#{name}", &options[:full]
|
||||
else
|
||||
if assume_complement
|
||||
define_method "search_filter_not_#{name}", &Item.search_filter_block(options, false, &block)
|
||||
end
|
||||
define_method "search_filter_#{name}", &Item.search_filter_block(options, true, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.single_search_filter(name, options={}, &block)
|
||||
options[:assume_complement] = false
|
||||
search_filter name, options, &block
|
||||
end
|
||||
|
||||
def self.search_filter_block(options, positive, &block)
|
||||
Proc.new { |str, user, scope|
|
||||
condition = block.arity == 1 ? block.call(str) : block.call(str, user)
|
||||
unless positive
|
||||
condition = condition.to_sql if condition.respond_to?(:to_sql)
|
||||
condition = "!(#{condition})"
|
||||
end
|
||||
scope = scope.send(options[:scope]) if options[:scope]
|
||||
scope.where(condition)
|
||||
}
|
||||
end
|
||||
|
||||
search_filter :name do |name|
|
||||
arel_table[:name].matches("%#{name}%")
|
||||
end
|
||||
|
||||
search_filter :description do |description|
|
||||
arel_table[:description].matches("%#{description}%")
|
||||
end
|
||||
|
||||
def self.adjective_filters
|
||||
@adjective_filters ||= {
|
||||
'nc' => arel_table[:rarity_index].in(NCRarities),
|
||||
'pb' => arel_table[:description].eq(PAINTBRUSH_SET_DESCRIPTION)
|
||||
}
|
||||
end
|
||||
|
||||
search_filter :is do |adjective|
|
||||
filter = adjective_filters[adjective]
|
||||
unless filter
|
||||
raise SearchError,
|
||||
"We don't know how an item can be \"#{adjective}\". " +
|
||||
"Did you mean is:nc or is:pb?"
|
||||
end
|
||||
filter
|
||||
end
|
||||
|
||||
USER_ADJECTIVES = {
|
||||
'own' => true,
|
||||
'owns' => true,
|
||||
'owned' => true,
|
||||
'want' => false,
|
||||
'wants' => false,
|
||||
'wanted' => false,
|
||||
'all' => nil,
|
||||
'items' => nil
|
||||
}
|
||||
def self.parse_user_adjective(adjective, user)
|
||||
unless USER_ADJECTIVES.has_key?(adjective)
|
||||
raise SearchError, "We don't understand user:#{adjective}. " +
|
||||
"Find items you own with user:owns, items you want with user:wants, or " +
|
||||
"both with user:all"
|
||||
end
|
||||
|
||||
unless user
|
||||
raise SearchError, "It looks like you're not logged in, so you don't own any items."
|
||||
end
|
||||
|
||||
USER_ADJECTIVES[adjective]
|
||||
end
|
||||
|
||||
search_filter :user do |adjective, user|
|
||||
# Though joins may seem more efficient here for the positive case, we need
|
||||
# to be able to handle cases like "user:owns user:wants", which breaks on
|
||||
# the JOIN approach. Just have to look up the IDs in advance.
|
||||
|
||||
owned_value = parse_user_adjective(adjective, user)
|
||||
hangers = ClosetHanger.arel_table
|
||||
items = user.closeted_items
|
||||
items = items.where(ClosetHanger.arel_table[:owned].eq(owned_value)) unless owned_value.nil?
|
||||
item_ids = items.map(&:id)
|
||||
# Though it's best to do arel_table[:id].in(item_ids), it breaks in this
|
||||
# version of Arel, and other conditions will overwrite this one. Since IDs
|
||||
# are guaranteed to be integers, let's just build our own string condition
|
||||
# and be done with it.
|
||||
|
||||
if item_ids.empty?
|
||||
raise SearchError, "You don't #{ClosetHanger.verb :you, owned_value} " +
|
||||
"any items yet. Head to Your Items to add some!"
|
||||
end
|
||||
|
||||
arel_table[:id].in(item_ids)
|
||||
end
|
||||
|
||||
search_filter :only do |species_name|
|
||||
begin
|
||||
id = Species.require_by_name(species_name).id
|
||||
rescue Species::NotFound => e
|
||||
raise SearchError, e.message
|
||||
end
|
||||
arel_table[:species_support_ids].eq(id.to_s)
|
||||
end
|
||||
|
||||
search_filter :species do |species_name|
|
||||
begin
|
||||
id = Species.require_by_name(species_name).id
|
||||
rescue Species::NotFound => e
|
||||
raise SearchError, e.message
|
||||
end
|
||||
ids = arel_table[:species_support_ids]
|
||||
ids.eq('').or(ids.matches_any([
|
||||
id,
|
||||
"#{id},%",
|
||||
"%,#{id},%",
|
||||
"%,#{id}"
|
||||
]))
|
||||
end
|
||||
|
||||
single_search_filter :type, {:limit => true, :scope => :join_swf_assets} do |zone_set_name|
|
||||
zone_set = Zone.find_set(zone_set_name)
|
||||
raise SearchError, "Type \"#{zone_set_name}\" does not exist" unless zone_set
|
||||
SwfAsset.arel_table[:zone_id].in(zone_set.map(&:id))
|
||||
end
|
||||
|
||||
single_search_filter :not_type, :full => lambda { |zone_set_name, user, scope|
|
||||
zone_set = Zone::ItemZoneSets[zone_set_name]
|
||||
raise SearchError, "Type \"#{zone_set_name}\" does not exist" unless zone_set
|
||||
psa = ParentSwfAssetRelationship.arel_table.alias
|
||||
sa = SwfAsset.arel_table.alias
|
||||
# Join to SWF assets, including the zone condition in the join so that
|
||||
# SWFs that don't match end up being NULL rows. Then we take the max SWF
|
||||
# asset ID, which is NULL if and only if there are no rows that matched
|
||||
# the zone requirement. If that max was NULL, return the object.
|
||||
item_ids = select(arel_table[:id]).joins(
|
||||
"LEFT JOIN #{ParentSwfAssetRelationship.table_name} #{psa.name} ON " +
|
||||
psa[:parent_type].eq(self.name).
|
||||
and(psa[:parent_id].eq(arel_table[:id])).
|
||||
to_sql
|
||||
).
|
||||
joins(
|
||||
"LEFT JOIN #{SwfAsset.table_name} #{sa.name} ON " +
|
||||
sa[:type].eq(SwfAssetType).
|
||||
and(sa[:id].eq(psa[:swf_asset_id])).
|
||||
and(sa[:zone_id].in(zone_set.map(&:id))).
|
||||
to_sql
|
||||
).
|
||||
group("#{table_name}.id").
|
||||
having("MAX(#{sa.name}.id) IS NULL"). # SwfAsset.arel_table[:id].maximum has no #eq
|
||||
map(&:id)
|
||||
scope.where(arel_table[:id].in(item_ids))
|
||||
}
|
||||
|
||||
class Condition < String
|
||||
attr_accessor :filter
|
||||
|
||||
def initialize
|
||||
@positive = true
|
||||
end
|
||||
|
||||
def filter?
|
||||
!@filter.nil?
|
||||
end
|
||||
|
||||
def to_filter!
|
||||
@filter = self.clone
|
||||
self.replace ''
|
||||
end
|
||||
|
||||
def negate!
|
||||
@positive = !@positive
|
||||
end
|
||||
|
||||
def narrow(scope, user)
|
||||
if SearchFilterScopes.include?(filter)
|
||||
polarized_filter = @positive ? filter : "not_#{filter}"
|
||||
Item.send("search_filter_#{polarized_filter}", self, user, scope)
|
||||
else
|
||||
raise SearchError, "Filter #{filter} does not exist"
|
||||
end
|
||||
end
|
||||
|
||||
def filter
|
||||
@filter || 'name'
|
||||
end
|
||||
|
||||
def inspect
|
||||
@filter ? "#{@filter}:#{super}" : super
|
||||
end
|
||||
end
|
||||
|
||||
class SearchError < ArgumentError;end
|
||||
end
|
||||
|
|
8
app/models/item/search.rb
Normal file
8
app/models/item/search.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
class Item
|
||||
module Search
|
||||
def self.error(key, *args)
|
||||
message = I18n.translate("items.search.errors.#{key}", *args)
|
||||
raise Item::Search::Error, message
|
||||
end
|
||||
end
|
||||
end
|
7
app/models/item/search/contradiction.rb
Normal file
7
app/models/item/search/contradiction.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
class Item
|
||||
module Search
|
||||
class Contradiction < Error
|
||||
|
||||
end
|
||||
end
|
||||
end
|
7
app/models/item/search/error.rb
Normal file
7
app/models/item/search/error.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
class Item
|
||||
module Search
|
||||
class Error < RuntimeError
|
||||
|
||||
end
|
||||
end
|
||||
end
|
11
app/models/item/search/field.rb
Normal file
11
app/models/item/search/field.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
class Item
|
||||
module Search
|
||||
class Field
|
||||
attr_reader :key
|
||||
|
||||
def initialize(key)
|
||||
@key = key
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
20
app/models/item/search/fields/flag.rb
Normal file
20
app/models/item/search/fields/flag.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
class Item
|
||||
module Search
|
||||
module Fields
|
||||
class Flag < Field
|
||||
def <<(filter)
|
||||
if @value.nil?
|
||||
@value = filter.positive?
|
||||
elsif @value != filter.positive?
|
||||
raise Item::Search::Contradiction,
|
||||
"flag #{key} both positive and negative"
|
||||
end
|
||||
end
|
||||
|
||||
def to_flex_params
|
||||
{key => @value}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
34
app/models/item/search/fields/set_field.rb
Normal file
34
app/models/item/search/fields/set_field.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
class Item
|
||||
module Search
|
||||
module Fields
|
||||
class SetField < Field
|
||||
def initialize(*args)
|
||||
super(*args)
|
||||
@values = {true => Set.new, false => Set.new}
|
||||
end
|
||||
|
||||
def <<(filter)
|
||||
if @values[!filter.positive?].include?(filter.value)
|
||||
raise Item::Search::Contradiction,
|
||||
"positive #{key} and negative #{key} both contain #{filter.value}"
|
||||
end
|
||||
|
||||
@values[filter.positive?] << filter.value
|
||||
end
|
||||
|
||||
def to_flex_params
|
||||
{
|
||||
:"_#{key}s" => nil_if_empty(@values[true]),
|
||||
:"_negative_#{key}s" => nil_if_empty(@values[false])
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def nil_if_empty(set)
|
||||
set.map { |value| {key => value} } unless set.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
29
app/models/item/search/fields/text_field.rb
Normal file
29
app/models/item/search/fields/text_field.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
class Item
|
||||
module Search
|
||||
module Fields
|
||||
class TextField < Field
|
||||
def initialize(*args)
|
||||
super(*args)
|
||||
@values = {true => '', false => ''}
|
||||
end
|
||||
|
||||
def <<(filter)
|
||||
@values[filter.positive?] << (filter.value + ' ')
|
||||
end
|
||||
|
||||
def to_flex_params
|
||||
{
|
||||
key => nil_if_empty(@values[true]),
|
||||
:"negative_#{key}" => nil_if_empty(@values[false])
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def nil_if_empty(str)
|
||||
str unless str.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
17
app/models/item/search/filter.rb
Normal file
17
app/models/item/search/filter.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
class Item
|
||||
module Search
|
||||
class Filter
|
||||
attr_reader :key, :value
|
||||
|
||||
def initialize(key, value, is_positive)
|
||||
@key = key
|
||||
@value = value
|
||||
@is_positive = is_positive
|
||||
end
|
||||
|
||||
def positive?
|
||||
@is_positive
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
197
app/models/item/search/query.rb
Normal file
197
app/models/item/search/query.rb
Normal file
|
@ -0,0 +1,197 @@
|
|||
class Item
|
||||
module Search
|
||||
class Query
|
||||
FIELD_CLASSES = {
|
||||
:is_nc => Fields::Flag,
|
||||
:is_pb => Fields::Flag,
|
||||
:species_support_id => Fields::SetField,
|
||||
:occupied_zone_id => Fields::SetField,
|
||||
:restricted_zone_id => Fields::SetField,
|
||||
:name => Fields::SetField,
|
||||
:user_closet_hanger_ownership => Fields::SetField
|
||||
}
|
||||
|
||||
def initialize(filters, user)
|
||||
@filters = filters
|
||||
@user = user
|
||||
end
|
||||
|
||||
def fields
|
||||
initial_fields.tap do |fields|
|
||||
@filters.each { |filter| fields[filter.key] << filter }
|
||||
end
|
||||
end
|
||||
|
||||
def to_flex_params
|
||||
fields.values.map(&:to_flex_params).inject(&:merge)
|
||||
end
|
||||
|
||||
def paginate(options={})
|
||||
begin
|
||||
flex_params = self.to_flex_params
|
||||
rescue Item::Search::Contradiction
|
||||
# If we have a contradictory query, no need to raise a stink about
|
||||
# it, but no need to actually run a search, either.
|
||||
return []
|
||||
end
|
||||
|
||||
final_flex_params = {
|
||||
:page => (options[:page] || 1),
|
||||
:size => (options[:per_page] || 30),
|
||||
:type => 'item'
|
||||
}.merge(flex_params)
|
||||
|
||||
locales = I18n.fallbacks[I18n.locale] &
|
||||
I18n.locales_with_neopets_language_code
|
||||
final_flex_params[:locale] = locales.first
|
||||
|
||||
# Extend the names/negative_names queries with the corresponding
|
||||
# localalized field names.
|
||||
if final_flex_params[:_names] || final_flex_params[:_negative_names]
|
||||
locale_entries = locales.map do |locale|
|
||||
boost = (locale == I18n.locale) ? 4 : 1
|
||||
"name.#{locale}^#{boost}"
|
||||
end
|
||||
|
||||
# We *could* have set _name_locales once as a partial, but Flex won't
|
||||
# let us call partials from inside other partials. Whatever. Assign
|
||||
# it to each name entry instead. I also feel bad doing this
|
||||
# afterwards, since it's kinda the field's job to return proper flex
|
||||
# params, but that's a refactor for another day.
|
||||
[:_names, :_negative_names].each do |key|
|
||||
if final_flex_params[key]
|
||||
final_flex_params[key].each do |name_query|
|
||||
name_query[:fields] = locale_entries
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Okay, yeah, looks like this really does deserve a refactor, like
|
||||
# _names and _negative_names do. (Or Flex could just make all variables
|
||||
# accessible from partials... hint, hint)
|
||||
[:_user_closet_hanger_ownerships, :_negative_user_closet_hanger_ownerships].each do |key|
|
||||
if final_flex_params[key]
|
||||
Item::Search.error 'not_logged_in' unless @user
|
||||
|
||||
final_flex_params[key].each do |entry|
|
||||
entry[:user_id] = @user.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
result = FlexSearch.item_search(final_flex_params)
|
||||
result.scoped_loaded_collection(
|
||||
:scopes => {'Item' => Item.includes(:translations)}
|
||||
)
|
||||
end
|
||||
|
||||
# Load the text query labels from I18n, so that when we see, say,
|
||||
# the filter "species:acara", we know it means species_support_id.
|
||||
TEXT_KEYS_BY_LABEL = {}
|
||||
OWNERSHIP_KEYWORDS = {}
|
||||
I18n.available_locales.each do |locale|
|
||||
TEXT_KEYS_BY_LABEL[locale] = {}
|
||||
OWNERSHIP_KEYWORDS[locale] = {}
|
||||
FIELD_CLASSES.keys.each do |key|
|
||||
# A locale can specify multiple labels for a key by separating by
|
||||
# commas: "occupies,zone,type"
|
||||
labels = I18n.translate("items.search.labels.#{key}",
|
||||
:locale => locale).split(',')
|
||||
labels.each { |label| TEXT_KEYS_BY_LABEL[locale][label] = key }
|
||||
|
||||
{:owns => true, :wants => false}.each do |key, value|
|
||||
translated_key = I18n.translate("items.search.labels.user_#{key}",
|
||||
:locale => locale)
|
||||
OWNERSHIP_KEYWORDS[locale][translated_key] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
TEXT_QUERY_RESOURCE_FINDERS = {
|
||||
:species => lambda { |name|
|
||||
species = Species.find_by_name(name)
|
||||
unless species
|
||||
Item::Search.error 'not_found.species', :species_name => name
|
||||
end
|
||||
species.id
|
||||
},
|
||||
:zone => lambda { |label|
|
||||
zone_set = Zone.with_plain_label(label)
|
||||
unless zone_set
|
||||
Item::Search.error 'not_found.zone', :zone_name => name
|
||||
end
|
||||
zone_set.map(&:id)
|
||||
},
|
||||
:ownership => lambda { |keyword|
|
||||
OWNERSHIP_KEYWORDS[I18n.locale][keyword].tap do |value|
|
||||
if value.nil?
|
||||
Item::Search.error 'not_found.ownership', :keyword => keyword
|
||||
end
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
TEXT_QUERY_RESOURCE_TYPES_BY_KEY = {
|
||||
:species_support_id => :species,
|
||||
:occupied_zone_id => :zone,
|
||||
:restricted_zone_id => :zone,
|
||||
:user_closet_hanger_ownership => :ownership
|
||||
}
|
||||
|
||||
TEXT_FILTER_EXPR = /([+-]?)(?:([a-z]+):)?(?:"([^"]+)"|(\S+))/
|
||||
def self.from_text(text, user=nil)
|
||||
filters = []
|
||||
|
||||
is_keyword = I18n.translate('items.search.flag_keywords.is')
|
||||
text.scan(TEXT_FILTER_EXPR) do |sign, label, quoted_value, unquoted_value|
|
||||
label ||= 'name'
|
||||
raw_value = quoted_value || unquoted_value
|
||||
is_positive = (sign != '-')
|
||||
|
||||
if label == is_keyword
|
||||
# is-filters are weird. "-is:nc" is transposed to something more
|
||||
# like "-nc:<nil>", then it's translated into a negative "is_nc"
|
||||
# flag. Fun fact: "nc:foobar" and "-nc:foobar" also work. A bonus,
|
||||
# I guess. There's probably a good way to refactor this to avoid
|
||||
# the unintended bonus syntax, but this is a darn good cheap
|
||||
# technique for the time being.
|
||||
label = raw_value
|
||||
raw_value = nil
|
||||
end
|
||||
|
||||
key = TEXT_KEYS_BY_LABEL[I18n.locale][label]
|
||||
if key.nil?
|
||||
message = I18n.translate('items.search.errors.not_found.label',
|
||||
:label => label)
|
||||
raise Item::Search::Error, message
|
||||
end
|
||||
|
||||
if TEXT_QUERY_RESOURCE_TYPES_BY_KEY.has_key?(key)
|
||||
resource_type = TEXT_QUERY_RESOURCE_TYPES_BY_KEY[key]
|
||||
finder = TEXT_QUERY_RESOURCE_FINDERS[resource_type]
|
||||
value = finder.call(raw_value)
|
||||
else
|
||||
value = raw_value
|
||||
end
|
||||
|
||||
filters << Filter.new(key, value, is_positive)
|
||||
end
|
||||
|
||||
self.new(filters, user)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# The fields start out empty, then have the filters inserted into 'em,
|
||||
# so that the fields can validate and aggregate their requirements.
|
||||
def initial_fields
|
||||
{}.tap do |fields|
|
||||
FIELD_CLASSES.map do |key, klass|
|
||||
fields[key] = klass.new(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -84,7 +84,7 @@ class Outfit < ActiveRecord::Base
|
|||
# ordered from bottom to top. Careful: this method is memoized, so if the
|
||||
# image layers change after its first call we'll get bad results.
|
||||
def image_layers
|
||||
@image_layers ||= visible_assets_with_images.sort { |a, b| a.zone.depth <=> b.zone.depth }
|
||||
@image_layers ||= visible_assets_with_images.sort { |a, b| a.depth <=> b.depth }
|
||||
end
|
||||
|
||||
# Creates and writes the thumbnail images for this outfit iff the new image
|
||||
|
@ -177,9 +177,10 @@ class Outfit < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def visible_assets
|
||||
biology_assets = pet_state.swf_assets
|
||||
biology_assets = pet_state.swf_assets.includes(:zone)
|
||||
object_assets = SwfAsset.object_assets.
|
||||
fitting_body_id(pet_state.pet_type.body_id).for_item_ids(worn_item_ids)
|
||||
fitting_body_id(pet_state.pet_type.body_id).for_item_ids(worn_item_ids).
|
||||
includes(:zone)
|
||||
|
||||
# Now for fun with bitmasks! Rather than building a bunch of integer arrays
|
||||
# here, we instead go low-level and use bit-level operations. Build the
|
||||
|
|
|
@ -2,8 +2,8 @@ require 'rocketamf/remote_gateway'
|
|||
|
||||
class Pet < ActiveRecord::Base
|
||||
GATEWAY_URL = 'http://www.neopets.com/amfphp/gateway.php'
|
||||
AMF_SERVICE_NAME = 'CustomPetService'
|
||||
PET_VIEWER_METHOD = 'getViewerData'
|
||||
PET_VIEWER = RocketAMF::RemoteGateway.new(GATEWAY_URL).
|
||||
service('CustomPetService').action('getViewerData')
|
||||
PET_NOT_FOUND_REMOTE_ERROR = 'PHP: Unable to retrieve records from the database.'
|
||||
WARDROBE_PATH = '/wardrobe'
|
||||
|
||||
|
@ -16,11 +16,22 @@ class Pet < ActiveRecord::Base
|
|||
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'
|
||||
begin
|
||||
envelope = Pet.amf_service.request(PET_VIEWER_METHOD, name, nil).
|
||||
fetch(:timeout => 2)
|
||||
neopets_language_code = I18n.neopets_language_code_for(options[:locale])
|
||||
envelope = PET_VIEWER.request([name, 0]).post(
|
||||
:timeout => 2,
|
||||
:headers => {
|
||||
'Cookie' => "lang=#{neopets_language_code}"
|
||||
}
|
||||
)
|
||||
rescue RocketAMF::RemoteGateway::AMFError => e
|
||||
if e.message == PET_NOT_FOUND_REMOTE_ERROR
|
||||
raise PetNotFound, "Pet #{name.inspect} does not exist"
|
||||
|
@ -31,18 +42,27 @@ class Pet < ActiveRecord::Base
|
|||
end
|
||||
contents = OpenStruct.new(envelope.messages[0].data.body)
|
||||
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,
|
||||
pet_data.color_id.to_i
|
||||
)
|
||||
self.pet_type.body_id = pet_data.body_id
|
||||
self.pet_type.origin_pet = self
|
||||
biology = pet_data.biology_by_zone
|
||||
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)
|
||||
|
||||
# in case this is running in a thread, explicitly grab an ActiveRecord
|
||||
# connection, to avoid connection conflicts
|
||||
Pet.connection_pool.with_connection do
|
||||
self.pet_type = PetType.find_or_initialize_by_species_id_and_color_id(
|
||||
pet_data.species_id.to_i,
|
||||
pet_data.color_id.to_i
|
||||
)
|
||||
self.pet_type.body_id = pet_data.body_id
|
||||
self.pet_type.origin_pet = self
|
||||
biology = pet_data.biology_by_zone
|
||||
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
|
||||
end
|
||||
|
||||
|
@ -65,6 +85,44 @@ class Pet < ActiveRecord::Base
|
|||
contributables
|
||||
end
|
||||
|
||||
def item_translation_candidates
|
||||
{}.tap do |candidates|
|
||||
if @items
|
||||
@items.each do |item|
|
||||
item.needed_translations.each do |locale|
|
||||
candidates[locale] ||= []
|
||||
candidates[locale] << item
|
||||
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}"
|
||||
reloaded_pet = Pet.load(name, :item_scope => Item.includes(:translations),
|
||||
:locale => locale)
|
||||
Pet.connection_pool.with_connection { reloaded_pet.save! }
|
||||
last_pet_loaded = reloaded_pet
|
||||
end
|
||||
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
|
||||
pet_type.save!
|
||||
if @pet_state
|
||||
|
@ -80,25 +138,12 @@ class Pet < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def self.load(name)
|
||||
def self.load(name, options={})
|
||||
pet = Pet.find_or_initialize_by_name(name)
|
||||
pet.load!
|
||||
pet.load!(options)
|
||||
pet
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.amf_service
|
||||
@amf_service ||= gateway.service AMF_SERVICE_NAME
|
||||
end
|
||||
|
||||
def self.gateway
|
||||
unless @gateway
|
||||
@gateway = RocketAMF::RemoteGateway.new(GATEWAY_URL)
|
||||
end
|
||||
@gateway
|
||||
end
|
||||
|
||||
class PetNotFound < Exception;end
|
||||
class DownloadError < Exception;end
|
||||
end
|
||||
|
|
|
@ -3,6 +3,8 @@ class PetType < ActiveRecord::Base
|
|||
IMAGE_CP_LOCATION_REGEX = %r{^/cp/(.+?)/1/1\.png$};
|
||||
IMAGE_CPN_ACCEPTABLE_NAME = /^[a-z0-9_]+$/
|
||||
|
||||
belongs_to :species
|
||||
belongs_to :color
|
||||
has_one :contribution, :as => :contributed
|
||||
has_many :pet_states
|
||||
has_many :pets
|
||||
|
@ -13,17 +15,20 @@ class PetType < ActiveRecord::Base
|
|||
|
||||
# Returns all pet types of a single standard color. The caller shouldn't care
|
||||
# which, though, in this implemention, it's always Blue. Don't depend on that.
|
||||
scope :single_standard_color, where(:color_id => Color::BasicIds[0])
|
||||
scope :single_standard_color, lambda { where(:color_id => Color.standard.first) }
|
||||
|
||||
scope :nonstandard_colors, where(:color_id => Color.nonstandard_ids)
|
||||
scope :nonstandard_colors, lambda { where(:color_id => Color.nonstandard) }
|
||||
|
||||
scope :includes_child_translations,
|
||||
lambda { includes({:color => :translations, :species => :translations}) }
|
||||
|
||||
def self.standard_pet_types_by_species_id
|
||||
@standard_pet_types_by_species_id ||=
|
||||
PetType.where(:color_id => Color::BasicIds).group_by(&:species_id)
|
||||
PetType.where(:color_id => Color.basic).includes_child_translations.
|
||||
group_by(&:species_id)
|
||||
end
|
||||
|
||||
def self.standard_body_ids
|
||||
@standard_body_ids ||= [].tap do |body_ids|
|
||||
[].tap do |body_ids|
|
||||
standard_pet_types_by_species_id.each do |species_id, pet_types|
|
||||
body_ids.concat(pet_types.map(&:body_id))
|
||||
end
|
||||
|
@ -32,8 +37,9 @@ class PetType < ActiveRecord::Base
|
|||
|
||||
def self.random_basic_per_species(species_ids)
|
||||
random_pet_types = []
|
||||
standards = self.standard_pet_types_by_species_id
|
||||
species_ids.each do |species_id|
|
||||
pet_types = standard_pet_types_by_species_id[species_id]
|
||||
pet_types = standards[species_id]
|
||||
random_pet_types << pet_types[rand(pet_types.size)] if pet_types
|
||||
end
|
||||
random_pet_types
|
||||
|
@ -51,40 +57,21 @@ class PetType < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def color_id=(new_color_id)
|
||||
@color = nil
|
||||
write_attribute('color_id', new_color_id)
|
||||
end
|
||||
|
||||
def color=(new_color)
|
||||
@color = new_color
|
||||
write_attribute('color_id', @color.id)
|
||||
end
|
||||
|
||||
def color
|
||||
@color ||= Color.find(color_id)
|
||||
end
|
||||
|
||||
def species_id=(new_species_id)
|
||||
@species = nil
|
||||
write_attribute('species_id', new_species_id)
|
||||
end
|
||||
|
||||
def species=(new_species)
|
||||
@species = new_species
|
||||
write_attribute('species_id', @species.id)
|
||||
end
|
||||
|
||||
def species
|
||||
@species ||= Species.find(species_id)
|
||||
end
|
||||
|
||||
def image_hash
|
||||
self['image_hash'] || basic_image_hash
|
||||
end
|
||||
|
||||
def basic_image_hash
|
||||
BasicHashes[species.name][color.name]
|
||||
I18n.with_locale(I18n.default_locale) do
|
||||
# Probably should move the basic hashes into the database someday.
|
||||
# Until then, access the hash using the English color/species names.
|
||||
|
||||
unless BasicHashes[species.name] && BasicHashes[species.name][color.name]
|
||||
raise "basic image hash for #{species.name}, #{color.name} not found"
|
||||
end
|
||||
|
||||
BasicHashes[species.name][color.name]
|
||||
end
|
||||
end
|
||||
|
||||
def human_name
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
class Species < PetAttribute
|
||||
fetch_objects!
|
||||
class Species < ActiveRecord::Base
|
||||
translates :name
|
||||
|
||||
def self.require_by_name(name)
|
||||
species = Species.find_by_name(name)
|
||||
raise NotFound, "Species \"#{name.humanize}\" does not exist" unless species
|
||||
species
|
||||
scope :alphabetical, lambda { includes(:translations).order(Species::Translation.arel_table[:name]) }
|
||||
|
||||
def as_json(options={})
|
||||
{:id => id, :name => human_name}
|
||||
end
|
||||
|
||||
class NotFound < ArgumentError;end
|
||||
def human_name
|
||||
name.capitalize
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,11 +5,21 @@ class StaticResource
|
|||
@objects
|
||||
end
|
||||
|
||||
def self.find(id)
|
||||
@objects[id-1]
|
||||
def self.find(id_or_ids)
|
||||
if id_or_ids.is_a?(Array)
|
||||
id_or_ids.uniq.map { |id| find_one(id) }
|
||||
else
|
||||
find_one(id_or_ids)
|
||||
end
|
||||
end
|
||||
|
||||
def self.count
|
||||
@objects.size
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.find_one(id)
|
||||
@objects[id - 1]
|
||||
end
|
||||
end
|
||||
|
|
|
@ -24,6 +24,10 @@ class SwfAsset < ActiveRecord::Base
|
|||
include SwfConverter
|
||||
converts_swfs :size => IMAGE_SIZES[:large], :output_sizes => IMAGE_SIZES.values
|
||||
|
||||
belongs_to :zone
|
||||
|
||||
scope :includes_depth, lambda { includes(:zone) }
|
||||
|
||||
def local_swf_path
|
||||
LOCAL_ASSET_DIR.join(local_path_within_outfit_swfs)
|
||||
end
|
||||
|
@ -197,15 +201,7 @@ class SwfAsset < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def body_specific?
|
||||
# If we already have assigned this a non-zero body id, or if the asset is
|
||||
# in a body-specific zone, or if the item is explicitly labeled as
|
||||
# body-specific (like Encased In Ice, which is body-specific but whose
|
||||
# assets occupy Background Item), then this asset is body-specific.
|
||||
(body_id? && body_id > 0) || self.zone.type_id < 3 || (@item && @item.explicitly_body_specific?)
|
||||
end
|
||||
|
||||
def zone
|
||||
Zone.find(zone_id)
|
||||
self.zone.type_id < 3 || (@item && @item.body_specific?)
|
||||
end
|
||||
|
||||
def origin_pet_type=(pet_type)
|
||||
|
|
|
@ -1,51 +1,28 @@
|
|||
class Zone < StaticResource
|
||||
AttributeNames = ['id', 'label', 'depth', 'type_id']
|
||||
ItemZoneSets = {}
|
||||
class Zone < ActiveRecord::Base
|
||||
translates :label, :plain_label
|
||||
|
||||
attr_reader *AttributeNames
|
||||
# When selecting zones that an asset occupies, we allow the zone to set
|
||||
# whether or not the zone is "sometimes" occupied. This is false by default.
|
||||
attr_writer :sometimes
|
||||
|
||||
def initialize(attributes)
|
||||
AttributeNames.each do |name|
|
||||
instance_variable_set "@#{name}", attributes[name]
|
||||
end
|
||||
end
|
||||
scope :alphabetical, lambda {
|
||||
includes_translations.order(Zone::Translation.arel_table[:label])
|
||||
}
|
||||
scope :includes_translations, lambda { includes(:translations) }
|
||||
scope :with_plain_label, lambda { |label|
|
||||
t = Zone::Translation.arel_table
|
||||
includes(:translations).where(t[:plain_label].eq(Zone.plainify_label(label)))
|
||||
}
|
||||
|
||||
def uncertain_label
|
||||
@sometimes ? "#{label} sometimes" : label
|
||||
end
|
||||
|
||||
def self.find_set(name)
|
||||
ItemZoneSets[plain(name)]
|
||||
def self.all_plain_labels
|
||||
Zone.select([:id]).includes(:translations).all.map(&:plain_label).uniq.sort
|
||||
end
|
||||
|
||||
def self.plain(name)
|
||||
name.delete('\- /').downcase
|
||||
end
|
||||
|
||||
n = 0
|
||||
@objects = YAML.load_file(Rails.root.join('config', 'zones.yml')).map do |a|
|
||||
a['id'] = (n += 1)
|
||||
obj = new(a)
|
||||
if obj.type_id == 2 || obj.type_id == 3
|
||||
plain_name = plain(obj.label)
|
||||
|
||||
ItemZoneSets[plain_name] ||= []
|
||||
ItemZoneSets[plain_name] << obj
|
||||
end
|
||||
obj
|
||||
end
|
||||
n = nil
|
||||
|
||||
# Add aliases to keys like "lowerforegrounditem" to "lowerforeground"
|
||||
# ...unless there's already such a key, like "backgrounditem" to "background",
|
||||
# in which case we don't, because that'd be silly.
|
||||
ItemZoneSets.keys.each do |name|
|
||||
if name.end_with?('item')
|
||||
stripped_name = name[0..-5]
|
||||
ItemZoneSets[stripped_name] ||= ItemZoneSets[name]
|
||||
end
|
||||
def self.plainify_label(label)
|
||||
label.delete('\- /').downcase
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
@import "partials/icon"
|
||||
@import url(http://fonts.googleapis.com/css?family=Droid+Sans:400,700)
|
||||
@import url(http://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic)
|
||||
@import url(http://fonts.googleapis.com/css?family=Calligraffitti)
|
||||
|
||||
/* Reset
|
||||
|
||||
|
@ -249,30 +252,3 @@ dd
|
|||
font-style: italic
|
||||
src: local("Delicious"), font-url("Delicious-Italic.otf")
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Droid Serif'
|
||||
font-style: normal
|
||||
font-weight: normal
|
||||
src: local("Droid Serif"), url("http://themes.googleusercontent.com/font?kit=70P0G8gxVDIV6F9om0DsKg") format("truetype")
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Droid Serif'
|
||||
font-style: normal
|
||||
font-weight: bold
|
||||
src: local("Droid Serif"), url("http://themes.googleusercontent.com/font?kit=QQt14e8dY39u-eYBZmppwf5Jgr8ufe5A6KahQF76Xmg") format("truetype")
|
||||
|
||||
|
||||
@font-face
|
||||
font-family: 'Droid Sans'
|
||||
font-style: normal
|
||||
font-weight: normal
|
||||
src: local("Droid Sans"), url("http://themes.googleusercontent.com/font?kit=POVDFY-UUf0WFR9DIMCU8g") format("truetype")
|
||||
|
||||
@font-face
|
||||
font-family: 'Calligraffitti'
|
||||
font-style: normal
|
||||
font-weight: normal
|
||||
src: local('Calligraffiti'), url('http://themes.googleusercontent.com/font?kit=vLVN2Y-z65rVu1R7lWdvyKIZAuDcNtpCWuPSaIR0Ie8') format('woff')
|
||||
|
||||
|
|
|
@ -53,13 +53,13 @@
|
|||
#item-zones
|
||||
%p
|
||||
%strong #{t '.zones.occupied_header'}:
|
||||
= list_zones @item.occupied_zones, :uncertain_label
|
||||
= list_zones @occupied_zones, :uncertain_label
|
||||
%p
|
||||
%strong #{t '.zones.restricted_header'}:
|
||||
- if @item.restricted_zones.empty?
|
||||
- if @restricted_zones.empty?
|
||||
= t '.zones.none'
|
||||
- else
|
||||
= list_zones @item.restricted_zones
|
||||
= list_zones @restricted_zones
|
||||
|
||||
#trade-hangers
|
||||
- [true, false].each do |owned|
|
||||
|
|
36
config/flex.yml
Normal file
36
config/flex.yml
Normal file
|
@ -0,0 +1,36 @@
|
|||
# ANCHORS litheral key: it will not be used as template
|
||||
# you can store here fragments of structures to reuse below
|
||||
ANCHORS:
|
||||
-
|
||||
|
||||
# This is a dynamic index name The settings and mapping below will work with any index.
|
||||
# The default index name generated by Flex is usually <application_name>_<environment>,
|
||||
# but you may have changed it in the initializers/flex.rb or you can hardcode it if you prefer.
|
||||
<%= Flex::Configuration.variables[:index] %>:
|
||||
|
||||
settings:
|
||||
number_of_shards: 5
|
||||
number_of_replicas: 1
|
||||
|
||||
# add your custom mappings here
|
||||
mappings:
|
||||
item:
|
||||
properties:
|
||||
# Name is an object of locale fields, which are in turn multi_fields.
|
||||
# First, an analyzed string for searching. Second, an untouched
|
||||
# string for sorting. Elasticsearch requires that both be expliticly
|
||||
# named in the mapping, but will handle the copy implicitly.
|
||||
name:
|
||||
type: object
|
||||
properties:
|
||||
<% I18n.usable_locales_with_neopets_language_code.each do |locale| %>
|
||||
<%= locale %>:
|
||||
type: multi_field
|
||||
fields:
|
||||
<%= locale %>:
|
||||
type: string
|
||||
index: analyzed
|
||||
untouched:
|
||||
type: string
|
||||
index: not_analyzed
|
||||
<% end %>
|
44
config/initializers/flex.rb
Normal file
44
config/initializers/flex.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
# see the detailed Configuration documentation at https://github.com/ddnexus/flex/wiki/Configuration
|
||||
|
||||
Flex::Configuration.configure do |config|
|
||||
|
||||
# you MUST add your indexed model names here
|
||||
config.flex_models = %w[ Item ClosetHanger ]
|
||||
|
||||
# Add the your result extenders here
|
||||
config.result_extenders |= [ FlexSearchExtender ]
|
||||
|
||||
# Add the default variables here
|
||||
# see also the details Variables documentation at https://github.com/ddnexus/flex/wiki/Variables
|
||||
# config.variables.add :index => 'my_index',
|
||||
# :type => 'project',
|
||||
# :anything => 'anything
|
||||
|
||||
# The custom url of your ElasticSearch server
|
||||
# config.base_uri = 'http://localhost:9200'
|
||||
|
||||
# Set it to true to log the debug infos (true by default in development mode)
|
||||
# config.debug = false
|
||||
|
||||
# Debug info are actually valid curl commands
|
||||
# config.debug_to_curl = false
|
||||
|
||||
# The custom logger you want Flex to use. Default Rails.logger
|
||||
# config.logger = Logger.new(STDERR)
|
||||
|
||||
# Custom config file path
|
||||
# config.config_file = '/custom/path/to/flex.yml',
|
||||
|
||||
# Custom flex dir path
|
||||
# config.flex_dir = '/custom/path/to/flex',
|
||||
|
||||
# The custom http_client you may want to implement
|
||||
# config.http_client = 'Your::Client'
|
||||
|
||||
# The options passed to the http_client. They are client specific.
|
||||
# config.http_client_options = {:timeout => 5}
|
||||
|
||||
# Experimental: checks the response and return a boolean (should raise?)
|
||||
# config.raise_proc = proc{|response| response.status >= 400}
|
||||
|
||||
end
|
58
config/initializers/locale_meta.rb
Normal file
58
config/initializers/locale_meta.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
module LocaleMeta
|
||||
PUBLIC_LOCALES = []
|
||||
USABLE_LOCALES = []
|
||||
NEOPETS_LANGUAGE_CODES_BY_LOCALE = {}
|
||||
LOCALES_WITH_NEOPETS_LANGUAGE_CODE = []
|
||||
COMPATIBLE_LOCALES = {}
|
||||
end
|
||||
|
||||
config = YAML.load_file(Rails.root.join('config', 'locale_meta.yml'))
|
||||
|
||||
config.each do |locale_str, locale_meta|
|
||||
locale = locale_str.to_sym
|
||||
|
||||
visibility = locale_meta['visibility']
|
||||
if visibility == 'public'
|
||||
LocaleMeta::PUBLIC_LOCALES << locale
|
||||
LocaleMeta::USABLE_LOCALES << locale
|
||||
elsif visibility == 'private'
|
||||
LocaleMeta::USABLE_LOCALES << locale
|
||||
end
|
||||
|
||||
if locale_meta.has_key?('neopets_language_code')
|
||||
neopets_language_code = locale_meta['neopets_language_code']
|
||||
LocaleMeta::NEOPETS_LANGUAGE_CODES_BY_LOCALE[locale] = neopets_language_code
|
||||
LocaleMeta::LOCALES_WITH_NEOPETS_LANGUAGE_CODE << locale
|
||||
elsif locale_meta.has_key?('compatible_with')
|
||||
compatible_locale = locale_meta['compatible_with'].to_sym
|
||||
LocaleMeta::COMPATIBLE_LOCALES[locale] = compatible_locale
|
||||
else
|
||||
raise "locale #{locale} must either have a neopets_language_code or " +
|
||||
"be compatible_with a locale that does"
|
||||
end
|
||||
end
|
||||
|
||||
LocaleMeta::USABLE_LOCALES_WITH_NEOPETS_LANGUAGE_CODE = LocaleMeta::USABLE_LOCALES &
|
||||
LocaleMeta::LOCALES_WITH_NEOPETS_LANGUAGE_CODE
|
||||
|
||||
module I18n
|
||||
def self.public_locales
|
||||
LocaleMeta::PUBLIC_LOCALES
|
||||
end
|
||||
|
||||
def self.usable_locales
|
||||
LocaleMeta::USABLE_LOCALES
|
||||
end
|
||||
|
||||
def self.locales_with_neopets_language_code
|
||||
LocaleMeta::LOCALES_WITH_NEOPETS_LANGUAGE_CODE
|
||||
end
|
||||
|
||||
def self.usable_locales_with_neopets_language_code
|
||||
LocaleMeta::USABLE_LOCALES_WITH_NEOPETS_LANGUAGE_CODE
|
||||
end
|
||||
|
||||
def self.neopets_language_code_for(locale)
|
||||
LocaleMeta::NEOPETS_LANGUAGE_CODES_BY_LOCALE[locale]
|
||||
end
|
||||
end
|
47
config/locale_meta.yml
Normal file
47
config/locale_meta.yml
Normal file
|
@ -0,0 +1,47 @@
|
|||
en:
|
||||
visibility: public
|
||||
neopets_language_code: en
|
||||
|
||||
en-MEEP:
|
||||
visibility: public
|
||||
compatible_with: en
|
||||
|
||||
pt:
|
||||
visibility: private
|
||||
neopets_language_code: pt
|
||||
|
||||
es:
|
||||
visibility: none
|
||||
neopets_language_code: es
|
||||
|
||||
nl:
|
||||
visibility: none
|
||||
neopets_language_code: nl
|
||||
|
||||
de:
|
||||
visibility: none
|
||||
neopets_language_code: de
|
||||
|
||||
fr:
|
||||
visibility: none
|
||||
neopets_language_code: fr
|
||||
|
||||
it:
|
||||
visibility: none
|
||||
neopets_language_code: it
|
||||
|
||||
zh-CN:
|
||||
visibility: none
|
||||
neopets_language_code: ch
|
||||
|
||||
zh-TW:
|
||||
visibility: none
|
||||
neopets_language_code: zh
|
||||
|
||||
ja:
|
||||
visibility: none
|
||||
neopets_language_code: ja
|
||||
|
||||
ko:
|
||||
visibility: none
|
||||
neopets_language_code: ko
|
|
@ -326,6 +326,30 @@ en:
|
|||
header: Brought to you by
|
||||
footer: Thanks!
|
||||
|
||||
search:
|
||||
errors:
|
||||
not_found:
|
||||
label: Filter "%{label}" does not exist. Is it spelled correctly?
|
||||
species:
|
||||
Species "%{species_name}" does not exist. Is it spelled correctly?
|
||||
zone: Zone "%{zone_name}" does not exist. Is it spelled correctly?
|
||||
ownership:
|
||||
I don't know what user:%{keyword} means. Is it spelled correctly?
|
||||
not_logged_in:
|
||||
The "user" filters are only available if you're logged in.
|
||||
flag_keywords:
|
||||
is: is
|
||||
labels:
|
||||
name: name
|
||||
is_nc: nc
|
||||
is_pb: pb
|
||||
species_support_id: species
|
||||
occupied_zone_id: occupies,zone,type
|
||||
restricted_zone_id: restricts
|
||||
user_closet_hanger_ownership: user
|
||||
user_owns: owns
|
||||
user_wants: wants
|
||||
|
||||
neopets_pages:
|
||||
create:
|
||||
success: Page %{index} saved!
|
||||
|
|
5
config/locales/pt.yml
Normal file
5
config/locales/pt.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
pt:
|
||||
locale_name: Portuguese
|
||||
|
||||
# This is a placeholder Portuguese locale, so that we can test things
|
||||
# involving its presence.
|
17
db/migrate/20130111213346_translate_items.rb
Normal file
17
db/migrate/20130111213346_translate_items.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
class TranslateItems < ActiveRecord::Migration
|
||||
def self.up
|
||||
rename_table :objects, :items
|
||||
Item.create_translation_table!({
|
||||
:name => :string,
|
||||
:description => :text,
|
||||
:rarity => :string
|
||||
}, {
|
||||
:migrate_data => true
|
||||
})
|
||||
end
|
||||
|
||||
def self.down
|
||||
Item.drop_translation_table! :migrate_data => true
|
||||
rename_table :items, :objects
|
||||
end
|
||||
end
|
11
db/migrate/20130121193957_create_species.rb
Normal file
11
db/migrate/20130121193957_create_species.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
class CreateSpecies < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :species
|
||||
Species.create_translation_table! :name => :string
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :species
|
||||
Species.drop_translation_table!
|
||||
end
|
||||
end
|
14
db/migrate/20130121205607_create_colors.rb
Normal file
14
db/migrate/20130121205607_create_colors.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
class CreateColors < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :colors do |t|
|
||||
t.boolean :basic
|
||||
t.boolean :standard
|
||||
end
|
||||
Color.create_translation_table! :name => :string
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :colors
|
||||
Color.drop_translation_table!
|
||||
end
|
||||
end
|
14
db/migrate/20130121221226_create_zones.rb
Normal file
14
db/migrate/20130121221226_create_zones.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
class CreateZones < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :zones do |t|
|
||||
t.integer :depth
|
||||
t.integer :type_id
|
||||
end
|
||||
Zone.create_translation_table! :label => :string, :plain_label => :string
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :zones
|
||||
Zone.drop_translation_table!
|
||||
end
|
||||
end
|
105
db/schema.rb
105
db/schema.rb
|
@ -1,3 +1,4 @@
|
|||
# encoding: UTF-8
|
||||
# This file is auto-generated from the current state of the database. Instead
|
||||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
|
@ -10,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20121006010446) do
|
||||
ActiveRecord::Schema.define(:version => 20130121221226) do
|
||||
|
||||
create_table "auth_servers", :force => true do |t|
|
||||
t.string "short_name", :limit => 10, :null => false
|
||||
|
@ -20,6 +21,13 @@ ActiveRecord::Schema.define(:version => 20121006010446) do
|
|||
t.string "secret", :limit => 64, :null => false
|
||||
end
|
||||
|
||||
create_table "campaigns", :force => true do |t|
|
||||
t.integer "goal_cents", :null => false
|
||||
t.integer "progress_cents", :null => false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "closet_hangers", :force => true do |t|
|
||||
t.integer "item_id"
|
||||
t.integer "user_id"
|
||||
|
@ -46,9 +54,20 @@ ActiveRecord::Schema.define(:version => 20121006010446) do
|
|||
|
||||
add_index "closet_lists", ["user_id"], :name => "index_closet_lists_on_user_id"
|
||||
|
||||
create_table "color_translations", :force => true do |t|
|
||||
t.integer "color_id"
|
||||
t.string "locale"
|
||||
t.string "name"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_index "color_translations", ["color_id"], :name => "index_color_translations_on_color_id"
|
||||
add_index "color_translations", ["locale"], :name => "index_color_translations_on_locale"
|
||||
|
||||
create_table "colors", :force => true do |t|
|
||||
t.string "name"
|
||||
t.boolean "basic", :default => false, :null => false
|
||||
t.boolean "basic"
|
||||
t.boolean "standard"
|
||||
end
|
||||
|
||||
create_table "contributions", :force => true do |t|
|
||||
|
@ -61,6 +80,14 @@ ActiveRecord::Schema.define(:version => 20121006010446) do
|
|||
add_index "contributions", ["contributed_id", "contributed_type"], :name => "index_contributions_on_contributed_id_and_contributed_type"
|
||||
add_index "contributions", ["user_id"], :name => "index_contributions_on_user_id"
|
||||
|
||||
create_table "donations", :force => true do |t|
|
||||
t.integer "amount_cents", :null => false
|
||||
t.integer "campaign_id", :null => false
|
||||
t.integer "user_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "forums", :force => true do |t|
|
||||
t.string "name"
|
||||
t.text "description"
|
||||
|
@ -80,16 +107,20 @@ ActiveRecord::Schema.define(:version => 20121006010446) do
|
|||
add_index "item_outfit_relationships", ["item_id"], :name => "index_item_outfit_relationships_on_item_id"
|
||||
add_index "item_outfit_relationships", ["outfit_id", "is_worn"], :name => "index_item_outfit_relationships_on_outfit_id_and_is_worn"
|
||||
|
||||
create_table "login_cookies", :force => true do |t|
|
||||
t.integer "user_id", :null => false
|
||||
t.integer "series", :null => false
|
||||
t.integer "token", :null => false
|
||||
create_table "item_translations", :force => true do |t|
|
||||
t.integer "item_id"
|
||||
t.string "locale"
|
||||
t.string "name"
|
||||
t.text "description"
|
||||
t.string "rarity"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_index "login_cookies", ["user_id", "series"], :name => "login_cookies_user_id_and_series"
|
||||
add_index "login_cookies", ["user_id"], :name => "login_cookies_user_id"
|
||||
add_index "item_translations", ["item_id"], :name => "index_item_translations_on_item_id"
|
||||
add_index "item_translations", ["locale"], :name => "index_item_translations_on_locale"
|
||||
|
||||
create_table "objects", :force => true do |t|
|
||||
create_table "items", :force => true do |t|
|
||||
t.text "zones_restrict", :null => false
|
||||
t.text "thumbnail_url", :limit => 16777215, :null => false
|
||||
t.string "name", :limit => 100, :null => false
|
||||
|
@ -108,8 +139,25 @@ ActiveRecord::Schema.define(:version => 20121006010446) do
|
|||
t.boolean "explicitly_body_specific", :default => false, :null => false
|
||||
end
|
||||
|
||||
add_index "objects", ["last_spidered"], :name => "objects_last_spidered"
|
||||
add_index "objects", ["name"], :name => "name"
|
||||
add_index "items", ["last_spidered"], :name => "objects_last_spidered"
|
||||
add_index "items", ["name"], :name => "name"
|
||||
|
||||
create_table "login_cookies", :force => true do |t|
|
||||
t.integer "user_id", :null => false
|
||||
t.integer "series", :null => false
|
||||
t.integer "token", :null => false
|
||||
end
|
||||
|
||||
add_index "login_cookies", ["user_id", "series"], :name => "login_cookies_user_id_and_series"
|
||||
add_index "login_cookies", ["user_id"], :name => "login_cookies_user_id"
|
||||
|
||||
create_table "outfit_features", :force => true do |t|
|
||||
t.integer "outfit_id", :null => false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.date "frontpage_start_date"
|
||||
t.date "frontpage_end_date"
|
||||
end
|
||||
|
||||
create_table "outfits", :force => true do |t|
|
||||
t.integer "pet_state_id"
|
||||
|
@ -121,6 +169,7 @@ ActiveRecord::Schema.define(:version => 20121006010446) do
|
|||
t.string "image"
|
||||
t.string "image_layers_hash"
|
||||
t.boolean "image_enqueued", :default => false, :null => false
|
||||
t.boolean "image_dirty", :default => false, :null => false
|
||||
end
|
||||
|
||||
add_index "outfits", ["pet_state_id"], :name => "index_outfits_on_pet_state_id"
|
||||
|
@ -179,6 +228,20 @@ ActiveRecord::Schema.define(:version => 20121006010446) do
|
|||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "species", :force => true do |t|
|
||||
end
|
||||
|
||||
create_table "species_translations", :force => true do |t|
|
||||
t.integer "species_id"
|
||||
t.string "locale"
|
||||
t.string "name"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_index "species_translations", ["locale"], :name => "index_species_translations_on_locale"
|
||||
add_index "species_translations", ["species_id"], :name => "index_species_translations_on_species_id"
|
||||
|
||||
create_table "swf_assets", :force => true do |t|
|
||||
t.string "type", :limit => 7, :null => false
|
||||
t.integer "remote_id", :limit => 3, :null => false
|
||||
|
@ -223,11 +286,21 @@ ActiveRecord::Schema.define(:version => 20121006010446) do
|
|||
t.integer "wanted_closet_hangers_visibility", :default => 1, :null => false
|
||||
end
|
||||
|
||||
create_table "zone_translations", :force => true do |t|
|
||||
t.integer "zone_id"
|
||||
t.string "locale"
|
||||
t.string "label"
|
||||
t.string "plain_label"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_index "zone_translations", ["locale"], :name => "index_zone_translations_on_locale"
|
||||
add_index "zone_translations", ["zone_id"], :name => "index_zone_translations_on_zone_id"
|
||||
|
||||
create_table "zones", :force => true do |t|
|
||||
t.integer "depth", :limit => 1, :null => false
|
||||
t.integer "type_id", :limit => 1, :null => false
|
||||
t.string "type", :limit => 40, :null => false
|
||||
t.string "label", :limit => 40, :null => false
|
||||
t.integer "depth"
|
||||
t.integer "type_id"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
215
db/seeds.rb
215
db/seeds.rb
|
@ -1,7 +1,208 @@
|
|||
# This file should contain all the record creation needed to seed the database with its default values.
|
||||
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
|
||||
#
|
||||
# Examples:
|
||||
#
|
||||
# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }])
|
||||
# Mayor.create(:name => 'Daley', :city => cities.first)
|
||||
Species.create(:id => 1, :name => "acara")
|
||||
Species.create(:id => 2, :name => "aisha")
|
||||
Species.create(:id => 3, :name => "blumaroo")
|
||||
Species.create(:id => 4, :name => "bori")
|
||||
Species.create(:id => 5, :name => "bruce")
|
||||
Species.create(:id => 6, :name => "buzz")
|
||||
Species.create(:id => 7, :name => "chia")
|
||||
Species.create(:id => 8, :name => "chomby")
|
||||
Species.create(:id => 9, :name => "cybunny")
|
||||
Species.create(:id => 10, :name => "draik")
|
||||
Species.create(:id => 11, :name => "elephante")
|
||||
Species.create(:id => 12, :name => "eyrie")
|
||||
Species.create(:id => 13, :name => "flotsam")
|
||||
Species.create(:id => 14, :name => "gelert")
|
||||
Species.create(:id => 15, :name => "gnorbu")
|
||||
Species.create(:id => 16, :name => "grarrl")
|
||||
Species.create(:id => 17, :name => "grundo")
|
||||
Species.create(:id => 18, :name => "hissi")
|
||||
Species.create(:id => 19, :name => "ixi")
|
||||
Species.create(:id => 20, :name => "jetsam")
|
||||
Species.create(:id => 21, :name => "jubjub")
|
||||
Species.create(:id => 22, :name => "kacheek")
|
||||
Species.create(:id => 23, :name => "kau")
|
||||
Species.create(:id => 24, :name => "kiko")
|
||||
Species.create(:id => 25, :name => "koi")
|
||||
Species.create(:id => 26, :name => "korbat")
|
||||
Species.create(:id => 27, :name => "kougra")
|
||||
Species.create(:id => 28, :name => "krawk")
|
||||
Species.create(:id => 29, :name => "kyrii")
|
||||
Species.create(:id => 30, :name => "lenny")
|
||||
Species.create(:id => 31, :name => "lupe")
|
||||
Species.create(:id => 32, :name => "lutari")
|
||||
Species.create(:id => 33, :name => "meerca")
|
||||
Species.create(:id => 34, :name => "moehog")
|
||||
Species.create(:id => 35, :name => "mynci")
|
||||
Species.create(:id => 36, :name => "nimmo")
|
||||
Species.create(:id => 37, :name => "ogrin")
|
||||
Species.create(:id => 38, :name => "peophin")
|
||||
Species.create(:id => 39, :name => "poogle")
|
||||
Species.create(:id => 40, :name => "pteri")
|
||||
Species.create(:id => 41, :name => "quiggle")
|
||||
Species.create(:id => 42, :name => "ruki")
|
||||
Species.create(:id => 43, :name => "scorchio")
|
||||
Species.create(:id => 44, :name => "shoyru")
|
||||
Species.create(:id => 45, :name => "skeith")
|
||||
Species.create(:id => 46, :name => "techo")
|
||||
Species.create(:id => 47, :name => "tonu")
|
||||
Species.create(:id => 48, :name => "tuskaninny")
|
||||
Species.create(:id => 49, :name => "uni")
|
||||
Species.create(:id => 50, :name => "usul")
|
||||
Species.create(:id => 51, :name => "wocky")
|
||||
Species.create(:id => 52, :name => "xweetok")
|
||||
Species.create(:id => 53, :name => "yurble")
|
||||
Species.create(:id => 54, :name => "zafara")
|
||||
|
||||
Color.create(:id => 1, :name => "alien", :basic => false, :standard => true)
|
||||
Color.create(:id => 2, :name => "apple", :basic => false, :standard => false)
|
||||
Color.create(:id => 3, :name => "asparagus", :basic => false, :standard => false)
|
||||
Color.create(:id => 4, :name => "aubergine", :basic => false, :standard => false)
|
||||
Color.create(:id => 5, :name => "avocado", :basic => false, :standard => false)
|
||||
Color.create(:id => 6, :name => "baby", :basic => false, :standard => false)
|
||||
Color.create(:id => 7, :name => "biscuit", :basic => false, :standard => true)
|
||||
Color.create(:id => 8, :name => "blue", :basic => true, :standard => true)
|
||||
Color.create(:id => 9, :name => "blueberry", :basic => false, :standard => false)
|
||||
Color.create(:id => 10, :name => "brown", :basic => false, :standard => true)
|
||||
Color.create(:id => 11, :name => "camouflage", :basic => false, :standard => true)
|
||||
Color.create(:id => 12, :name => "carrot", :basic => false, :standard => false)
|
||||
Color.create(:id => 13, :name => "checkered", :basic => false, :standard => true)
|
||||
Color.create(:id => 14, :name => "chocolate", :basic => false, :standard => true)
|
||||
Color.create(:id => 15, :name => "chokato", :basic => false, :standard => false)
|
||||
Color.create(:id => 16, :name => "christmas", :basic => false, :standard => true)
|
||||
Color.create(:id => 17, :name => "clay", :basic => false, :standard => true)
|
||||
Color.create(:id => 18, :name => "cloud", :basic => false, :standard => true)
|
||||
Color.create(:id => 19, :name => "coconut", :basic => false, :standard => true)
|
||||
Color.create(:id => 20, :name => "custard", :basic => false, :standard => true)
|
||||
Color.create(:id => 21, :name => "darigan", :basic => false, :standard => true)
|
||||
Color.create(:id => 22, :name => "desert", :basic => false, :standard => true)
|
||||
Color.create(:id => 23, :name => "disco", :basic => false, :standard => true)
|
||||
Color.create(:id => 24, :name => "durian", :basic => false, :standard => false)
|
||||
Color.create(:id => 25, :name => "electric", :basic => false, :standard => true)
|
||||
Color.create(:id => 26, :name => "faerie", :basic => false, :standard => true)
|
||||
Color.create(:id => 27, :name => "fire", :basic => false, :standard => true)
|
||||
Color.create(:id => 28, :name => "garlic", :basic => false, :standard => true)
|
||||
Color.create(:id => 29, :name => "ghost", :basic => false, :standard => true)
|
||||
Color.create(:id => 30, :name => "glowing", :basic => false, :standard => true)
|
||||
Color.create(:id => 31, :name => "gold", :basic => false, :standard => true)
|
||||
Color.create(:id => 32, :name => "gooseberry", :basic => false, :standard => false)
|
||||
Color.create(:id => 33, :name => "grape", :basic => false, :standard => false)
|
||||
Color.create(:id => 34, :name => "green", :basic => true, :standard => true)
|
||||
Color.create(:id => 35, :name => "grey", :basic => false, :standard => true)
|
||||
Color.create(:id => 36, :name => "halloween", :basic => false, :standard => true)
|
||||
Color.create(:id => 37, :name => "ice", :basic => false, :standard => true)
|
||||
Color.create(:id => 38, :name => "invisible", :basic => false, :standard => true)
|
||||
Color.create(:id => 39, :name => "island", :basic => false, :standard => true)
|
||||
Color.create(:id => 40, :name => "jelly", :basic => false, :standard => true)
|
||||
Color.create(:id => 41, :name => "lemon", :basic => false, :standard => false)
|
||||
Color.create(:id => 42, :name => "lime", :basic => false, :standard => false)
|
||||
Color.create(:id => 43, :name => "mallow", :basic => false, :standard => true)
|
||||
Color.create(:id => 44, :name => "maraquan", :basic => false, :standard => false)
|
||||
Color.create(:id => 45, :name => "msp", :basic => false, :standard => true)
|
||||
Color.create(:id => 46, :name => "mutant", :basic => false, :standard => false)
|
||||
Color.create(:id => 47, :name => "orange", :basic => false, :standard => false)
|
||||
Color.create(:id => 48, :name => "pea", :basic => false, :standard => false)
|
||||
Color.create(:id => 49, :name => "peach", :basic => false, :standard => false)
|
||||
Color.create(:id => 50, :name => "pear", :basic => false, :standard => false)
|
||||
Color.create(:id => 51, :name => "pepper", :basic => false, :standard => false)
|
||||
Color.create(:id => 52, :name => "pineapple", :basic => false, :standard => false)
|
||||
Color.create(:id => 53, :name => "pink", :basic => false, :standard => true)
|
||||
Color.create(:id => 54, :name => "pirate", :basic => false, :standard => true)
|
||||
Color.create(:id => 55, :name => "plum", :basic => false, :standard => false)
|
||||
Color.create(:id => 56, :name => "plushie", :basic => false, :standard => true)
|
||||
Color.create(:id => 57, :name => "purple", :basic => false, :standard => true)
|
||||
Color.create(:id => 58, :name => "quigukiboy", :basic => false, :standard => true)
|
||||
Color.create(:id => 59, :name => "quigukigirl", :basic => false, :standard => true)
|
||||
Color.create(:id => 60, :name => "rainbow", :basic => false, :standard => true)
|
||||
Color.create(:id => 61, :name => "red", :basic => true, :standard => true)
|
||||
Color.create(:id => 62, :name => "robot", :basic => false, :standard => true)
|
||||
Color.create(:id => 63, :name => "royalboy", :basic => false, :standard => true)
|
||||
Color.create(:id => 64, :name => "royalgirl", :basic => false, :standard => true)
|
||||
Color.create(:id => 65, :name => "shadow", :basic => false, :standard => true)
|
||||
Color.create(:id => 66, :name => "silver", :basic => false, :standard => true)
|
||||
Color.create(:id => 67, :name => "sketch", :basic => false, :standard => true)
|
||||
Color.create(:id => 68, :name => "skunk", :basic => false, :standard => true)
|
||||
Color.create(:id => 69, :name => "snot", :basic => false, :standard => true)
|
||||
Color.create(:id => 70, :name => "snow", :basic => false, :standard => false)
|
||||
Color.create(:id => 71, :name => "speckled", :basic => false, :standard => true)
|
||||
Color.create(:id => 72, :name => "split", :basic => false, :standard => true)
|
||||
Color.create(:id => 73, :name => "sponge", :basic => false, :standard => true)
|
||||
Color.create(:id => 74, :name => "spotted", :basic => false, :standard => true)
|
||||
Color.create(:id => 75, :name => "starry", :basic => false, :standard => true)
|
||||
Color.create(:id => 76, :name => "strawberry", :basic => false, :standard => true)
|
||||
Color.create(:id => 77, :name => "striped", :basic => false, :standard => true)
|
||||
Color.create(:id => 78, :name => "thornberry", :basic => false, :standard => false)
|
||||
Color.create(:id => 79, :name => "tomato", :basic => false, :standard => false)
|
||||
Color.create(:id => 80, :name => "tyrannian", :basic => false, :standard => true)
|
||||
Color.create(:id => 81, :name => "usukiboy", :basic => false, :standard => true)
|
||||
Color.create(:id => 82, :name => "usukigirl", :basic => false, :standard => true)
|
||||
Color.create(:id => 83, :name => "white", :basic => false, :standard => true)
|
||||
Color.create(:id => 84, :name => "yellow", :basic => true, :standard => true)
|
||||
Color.create(:id => 85, :name => "zombie", :basic => false, :standard => true)
|
||||
Color.create(:id => 86, :name => "onion", :basic => false, :standard => false)
|
||||
Color.create(:id => 87, :name => "magma", :basic => false, :standard => true)
|
||||
Color.create(:id => 88, :name => "relic", :basic => false, :standard => true)
|
||||
Color.create(:id => 89, :name => "woodland", :basic => false, :standard => true)
|
||||
Color.create(:id => 90, :name => "transparent", :basic => false, :standard => true)
|
||||
Color.create(:id => 91, :name => "maractite", :basic => false, :standard => true)
|
||||
Color.create(:id => 92, :name => "8-bit", :basic => false, :standard => true)
|
||||
Color.create(:id => 93, :name => "swamp gas", :basic => false, :standard => true)
|
||||
Color.create(:id => 94, :name => "water", :basic => false, :standard => true)
|
||||
Color.create(:id => 95, :name => "wraith", :basic => false, :standard => true)
|
||||
Color.create(:id => 96, :name => "eventide", :basic => false, :standard => true)
|
||||
Color.create(:id => 97, :name => "elderlyboy", :basic => false, :standard => true)
|
||||
Color.create(:id => 98, :name => "elderlygirl", :basic => false, :standard => true)
|
||||
Color.create(:id => 99, :name => "stealthy", :basic => false, :standard => true)
|
||||
Color.create(:id => 100, :name => "dimensional", :basic => false, :standard => true)
|
||||
|
||||
Zone.create(:id => 1, :label => "Music", :plain_label => "music", :depth => 1, :type_id => 4)
|
||||
Zone.create(:id => 2, :label => "Sound Effects", :plain_label => "soundeffects", :depth => 2, :type_id => 4)
|
||||
Zone.create(:id => 3, :label => "Background", :plain_label => "background", :depth => 3, :type_id => 3)
|
||||
Zone.create(:id => 4, :label => "Biology Effects", :plain_label => "biologyeffects", :depth => 6, :type_id => 1)
|
||||
Zone.create(:id => 5, :label => "Hind Biology", :plain_label => "hindbiology", :depth => 7, :type_id => 1)
|
||||
Zone.create(:id => 6, :label => "Markings", :plain_label => "markings", :depth => 8, :type_id => 2)
|
||||
Zone.create(:id => 7, :label => "Hind Disease", :plain_label => "hinddisease", :depth => 9, :type_id => 1)
|
||||
Zone.create(:id => 8, :label => "Hind Cover", :plain_label => "hindcover", :depth => 10, :type_id => 2)
|
||||
Zone.create(:id => 9, :label => "Hind Transient Biology", :plain_label => "hindtransientbiology", :depth => 11, :type_id => 1)
|
||||
Zone.create(:id => 10, :label => "Hind Drippings", :plain_label => "hinddrippings", :depth => 12, :type_id => 1)
|
||||
Zone.create(:id => 11, :label => "Backpack", :plain_label => "backpack", :depth => 13, :type_id => 2)
|
||||
Zone.create(:id => 12, :label => "Wings Transient Biology", :plain_label => "wingstransientbiology", :depth => 14, :type_id => 1)
|
||||
Zone.create(:id => 13, :label => "Wings", :plain_label => "wings", :depth => 15, :type_id => 2)
|
||||
Zone.create(:id => 14, :label => "Hair Back", :plain_label => "hairback", :depth => 17, :type_id => 1)
|
||||
Zone.create(:id => 15, :label => "Body", :plain_label => "body", :depth => 18, :type_id => 1)
|
||||
Zone.create(:id => 16, :label => "Markings", :plain_label => "markings", :depth => 19, :type_id => 2)
|
||||
Zone.create(:id => 17, :label => "Body Disease", :plain_label => "bodydisease", :depth => 20, :type_id => 1)
|
||||
Zone.create(:id => 18, :label => "Feet Transient Biology", :plain_label => "feettransientbiology", :depth => 21, :type_id => 1)
|
||||
Zone.create(:id => 19, :label => "Shoes", :plain_label => "shoes", :depth => 22, :type_id => 2)
|
||||
Zone.create(:id => 20, :label => "Lower-body Transient Biology", :plain_label => "lowerbodytransientbiology", :depth => 23, :type_id => 1)
|
||||
Zone.create(:id => 21, :label => "Trousers", :plain_label => "trousers", :depth => 24, :type_id => 2)
|
||||
Zone.create(:id => 22, :label => "Upper-body Transient Biology", :plain_label => "upperbodytransientbiology", :depth => 25, :type_id => 1)
|
||||
Zone.create(:id => 23, :label => "Shirt/Dress", :plain_label => "shirtdress", :depth => 26, :type_id => 2)
|
||||
Zone.create(:id => 24, :label => "Necklace", :plain_label => "necklace", :depth => 28, :type_id => 2)
|
||||
Zone.create(:id => 25, :label => "Gloves", :plain_label => "gloves", :depth => 29, :type_id => 2)
|
||||
Zone.create(:id => 26, :label => "Jacket", :plain_label => "jacket", :depth => 30, :type_id => 2)
|
||||
Zone.create(:id => 27, :label => "Collar", :plain_label => "collar", :depth => 31, :type_id => 2)
|
||||
Zone.create(:id => 28, :label => "Body Drippings", :plain_label => "bodydrippings", :depth => 32, :type_id => 1)
|
||||
Zone.create(:id => 29, :label => "Ruff", :plain_label => "ruff", :depth => 33, :type_id => 1)
|
||||
Zone.create(:id => 30, :label => "Head", :plain_label => "head", :depth => 34, :type_id => 1)
|
||||
Zone.create(:id => 31, :label => "Markings", :plain_label => "markings", :depth => 35, :type_id => 2)
|
||||
Zone.create(:id => 32, :label => "Head Disease", :plain_label => "headdisease", :depth => 36, :type_id => 1)
|
||||
Zone.create(:id => 33, :label => "Eyes", :plain_label => "eyes", :depth => 37, :type_id => 1)
|
||||
Zone.create(:id => 34, :label => "Mouth", :plain_label => "mouth", :depth => 38, :type_id => 1)
|
||||
Zone.create(:id => 35, :label => "Glasses", :plain_label => "glasses", :depth => 41, :type_id => 2)
|
||||
Zone.create(:id => 36, :label => "Earrings", :plain_label => "earrings", :depth => 39, :type_id => 2)
|
||||
Zone.create(:id => 37, :label => "Hair Front", :plain_label => "hairfront", :depth => 40, :type_id => 1)
|
||||
Zone.create(:id => 38, :label => "Head Transient Biology", :plain_label => "headtransientbiology", :depth => 42, :type_id => 1)
|
||||
Zone.create(:id => 39, :label => "Head Drippings", :plain_label => "headdrippings", :depth => 43, :type_id => 1)
|
||||
Zone.create(:id => 40, :label => "Hat", :plain_label => "hat", :depth => 44, :type_id => 2)
|
||||
Zone.create(:id => 41, :label => "Earrings", :plain_label => "earrings", :depth => 45, :type_id => 2)
|
||||
Zone.create(:id => 42, :label => "Right-hand Item", :plain_label => "righthand", :depth => 46, :type_id => 2)
|
||||
Zone.create(:id => 43, :label => "Left-hand Item", :plain_label => "lefthand", :depth => 47, :type_id => 2)
|
||||
Zone.create(:id => 44, :label => "Higher Foreground Item", :plain_label => "higherforeground", :depth => 49, :type_id => 3)
|
||||
Zone.create(:id => 45, :label => "Lower Foreground Item", :plain_label => "lowerforeground", :depth => 50, :type_id => 3)
|
||||
Zone.create(:id => 46, :label => "Static", :plain_label => "static", :depth => 48, :type_id => 3)
|
||||
Zone.create(:id => 47, :label => "Thought Bubble", :plain_label => "thoughtbubble", :depth => 51, :type_id => 3)
|
||||
Zone.create(:id => 48, :label => "Background Item", :plain_label => "background", :depth => 4, :type_id => 3)
|
||||
Zone.create(:id => 49, :label => "Right-hand Item", :plain_label => "righthand", :depth => 5, :type_id => 2)
|
||||
Zone.create(:id => 50, :label => "Hat", :plain_label => "hat", :depth => 16, :type_id => 2)
|
||||
Zone.create(:id => 51, :label => "Belt", :plain_label => "belt", :depth => 27, :type_id => 2)
|
||||
Zone.create(:id => 52, :label => "Foreground", :plain_label => "foreground", :depth => 52, :type_id => 3)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
require 'net/http'
|
||||
require 'rocketamf'
|
||||
require File.join(File.dirname(__FILE__), 'remote_gateway', 'service')
|
||||
require File.join(File.dirname(__FILE__), 'remote_gateway', 'request')
|
||||
|
||||
module RocketAMF
|
||||
class RemoteGateway
|
||||
|
|
18
lib/rocketamf/remote_gateway/action.rb
Normal file
18
lib/rocketamf/remote_gateway/action.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
require File.join(File.dirname(__FILE__), 'request')
|
||||
|
||||
module RocketAMF
|
||||
class RemoteGateway
|
||||
class Action
|
||||
attr_reader :service, :name
|
||||
|
||||
def initialize(service, name)
|
||||
@service = service
|
||||
@name = name
|
||||
end
|
||||
|
||||
def request(params)
|
||||
Request.new(self, params)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,18 +5,21 @@ module RocketAMF
|
|||
class Request
|
||||
ERROR_CODE = 'AMFPHP_RUNTIME_ERROR'
|
||||
|
||||
def initialize(service, method, *params)
|
||||
@service = service
|
||||
@method = method
|
||||
def initialize(action, params)
|
||||
@action = action
|
||||
@params = params
|
||||
end
|
||||
|
||||
def fetch(options={})
|
||||
uri = @service.gateway.uri
|
||||
def post(options={})
|
||||
uri = @action.service.gateway.uri
|
||||
data = envelope.serialize
|
||||
|
||||
req = Net::HTTP::Post.new(uri.path)
|
||||
req.body = data
|
||||
headers = options[:headers] || {}
|
||||
headers.each do |key, value|
|
||||
req[key] = value
|
||||
end
|
||||
|
||||
res = nil
|
||||
|
||||
|
@ -68,8 +71,8 @@ module RocketAMF
|
|||
|
||||
def remoting_message
|
||||
message = Values::RemotingMessage.new
|
||||
message.source = @service.name
|
||||
message.operation = @method
|
||||
message.source = @action.service.name
|
||||
message.operation = @action.name
|
||||
message.body = @params
|
||||
message
|
||||
end
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
require File.join(File.dirname(__FILE__), 'action')
|
||||
|
||||
module RocketAMF
|
||||
class RemoteGateway
|
||||
class Service
|
||||
|
@ -8,8 +10,8 @@ module RocketAMF
|
|||
@name = name
|
||||
end
|
||||
|
||||
def request(method, *params)
|
||||
Request.new(self, method, *params)
|
||||
def action(name)
|
||||
Action.new(self, name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
@charset "UTF-8";
|
||||
@import url(http://fonts.googleapis.com/css?family=Droid+Sans:400,700);
|
||||
@import url(http://fonts.googleapis.com/css?family=Droid+Serif:400,700,400italic);
|
||||
@import url(http://fonts.googleapis.com/css?family=Calligraffitti);
|
||||
/* Reset */
|
||||
/* line 5, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 8, ../../../app/stylesheets/_layout.sass */
|
||||
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p,
|
||||
blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em,
|
||||
font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b,
|
||||
|
@ -16,12 +19,12 @@ caption, tbody, tfoot, thead, tr, th, td {
|
|||
}
|
||||
|
||||
/* Typography */
|
||||
/* line 20, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 23, ../../../app/stylesheets/_layout.sass */
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* line 23, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 26, ../../../app/stylesheets/_layout.sass */
|
||||
body {
|
||||
background: white;
|
||||
color: #004400;
|
||||
|
@ -30,60 +33,60 @@ body {
|
|||
line-height: 1.5;
|
||||
}
|
||||
|
||||
/* line 31, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 34, ../../../app/stylesheets/_layout.sass */
|
||||
a {
|
||||
color: #226622;
|
||||
}
|
||||
|
||||
/* line 34, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 37, ../../../app/stylesheets/_layout.sass */
|
||||
p {
|
||||
font-family: "Droid Serif", Georgia, "Times New Roman", Times, serif;
|
||||
}
|
||||
|
||||
/* line 37, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 40, ../../../app/stylesheets/_layout.sass */
|
||||
input, button, select {
|
||||
font-family: inherit;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
/* line 42, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 45, ../../../app/stylesheets/_layout.sass */
|
||||
p {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
/* line 45, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 48, ../../../app/stylesheets/_layout.sass */
|
||||
h1, h2, h3 {
|
||||
font-family: Delicious, Helvetica, Arial, Verdana, sans-serif;
|
||||
}
|
||||
|
||||
/* line 48, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 51, ../../../app/stylesheets/_layout.sass */
|
||||
h1 {
|
||||
font-size: 3em;
|
||||
line-height: 1;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
/* line 53, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 56, ../../../app/stylesheets/_layout.sass */
|
||||
h2 {
|
||||
font-size: 2em;
|
||||
margin-bottom: 0.75em;
|
||||
}
|
||||
|
||||
/* line 57, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 60, ../../../app/stylesheets/_layout.sass */
|
||||
h3 {
|
||||
font-size: 1.5em;
|
||||
line-height: 1;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
/* line 62, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 65, ../../../app/stylesheets/_layout.sass */
|
||||
.inline-image, body.pets-bulk #bulk-pets-form ul img {
|
||||
margin-right: 1em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Main */
|
||||
/* line 70, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 73, ../../../app/stylesheets/_layout.sass */
|
||||
#container {
|
||||
margin: 1em auto;
|
||||
padding-top: 3em;
|
||||
|
@ -91,12 +94,12 @@ h3 {
|
|||
width: 800px;
|
||||
}
|
||||
|
||||
/* line 76, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 79, ../../../app/stylesheets/_layout.sass */
|
||||
input, button, select, label {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* line 79, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 82, ../../../app/stylesheets/_layout.sass */
|
||||
input[type=text], body.pets-bulk #bulk-pets-form textarea, input[type=password], input[type=search], input[type=number], select, textarea {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
|
@ -105,17 +108,17 @@ input[type=text], body.pets-bulk #bulk-pets-form textarea, input[type=password],
|
|||
color: #448844;
|
||||
padding: 0.25em;
|
||||
}
|
||||
/* line 85, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 88, ../../../app/stylesheets/_layout.sass */
|
||||
input[type=text]:focus, body.pets-bulk #bulk-pets-form textarea:focus, input[type=text]:active, body.pets-bulk #bulk-pets-form textarea:active, input[type=password]:focus, input[type=password]:active, input[type=search]:focus, input[type=search]:active, input[type=number]:focus, input[type=number]:active, select:focus, select:active, textarea:focus, textarea:active {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* line 88, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 91, ../../../app/stylesheets/_layout.sass */
|
||||
textarea {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
/* line 91, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 94, ../../../app/stylesheets/_layout.sass */
|
||||
a.button, input[type=submit], button {
|
||||
/* http://www.zurb.com/blog_uploads/0000/0617/buttons-03.html */
|
||||
-moz-border-radius: 5px;
|
||||
|
@ -146,7 +149,7 @@ a.button:hover, input[type=submit]:hover, button:hover {
|
|||
a.button:active, input[type=submit]:active, button:active {
|
||||
top: 1px;
|
||||
}
|
||||
/* line 93, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 96, ../../../app/stylesheets/_layout.sass */
|
||||
a.button.loud, input[type=submit].loud, button.loud {
|
||||
background: #ff5c00 url('/images/alert-overlay.png?1344550430') repeat-x;
|
||||
font-size: 125%;
|
||||
|
@ -157,21 +160,21 @@ a.button.loud:hover, input[type=submit].loud:hover, button.loud:hover {
|
|||
background-color: #ee4b00;
|
||||
}
|
||||
|
||||
/* line 96, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 99, ../../../app/stylesheets/_layout.sass */
|
||||
ul.buttons {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
/* line 98, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 101, ../../../app/stylesheets/_layout.sass */
|
||||
ul.buttons li {
|
||||
list-style: none;
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
/* line 101, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 104, ../../../app/stylesheets/_layout.sass */
|
||||
ul.buttons li, ul.buttons li form {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* line 104, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 107, ../../../app/stylesheets/_layout.sass */
|
||||
#footer {
|
||||
clear: both;
|
||||
font-size: 75%;
|
||||
|
@ -179,69 +182,69 @@ ul.buttons li, ul.buttons li form {
|
|||
padding-top: 2em;
|
||||
text-align: center;
|
||||
}
|
||||
/* line 110, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 113, ../../../app/stylesheets/_layout.sass */
|
||||
#footer ul, #footer div {
|
||||
display: inline;
|
||||
margin: 0 1em;
|
||||
}
|
||||
/* line 113, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 116, ../../../app/stylesheets/_layout.sass */
|
||||
#footer li, #footer div ul {
|
||||
display: inline;
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
/* line 116, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 119, ../../../app/stylesheets/_layout.sass */
|
||||
#footer #locale-form {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/* line 119, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 122, ../../../app/stylesheets/_layout.sass */
|
||||
.success, .alert, .warning {
|
||||
margin-bottom: 1em;
|
||||
padding: 0.25em 0.5em;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* line 124, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 127, ../../../app/stylesheets/_layout.sass */
|
||||
.success {
|
||||
background: #e6efc2;
|
||||
border: 1px solid #c6d880;
|
||||
color: #264409;
|
||||
}
|
||||
|
||||
/* line 127, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 130, ../../../app/stylesheets/_layout.sass */
|
||||
.alert {
|
||||
background: #fbe3e4;
|
||||
border: 1px solid #fbc2c4;
|
||||
color: #8a1f11;
|
||||
}
|
||||
|
||||
/* line 130, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 133, ../../../app/stylesheets/_layout.sass */
|
||||
.warning {
|
||||
background: #fff6bf;
|
||||
border: 1px solid #ffd324;
|
||||
color: #514721;
|
||||
}
|
||||
|
||||
/* line 133, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 136, ../../../app/stylesheets/_layout.sass */
|
||||
#userbar {
|
||||
font-family: Delicious, Helvetica, Arial, Verdana, sans-serif;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
/* line 138, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 141, ../../../app/stylesheets/_layout.sass */
|
||||
#userbar > * {
|
||||
display: inline;
|
||||
margin: 0 0.25em;
|
||||
}
|
||||
|
||||
/* line 142, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 145, ../../../app/stylesheets/_layout.sass */
|
||||
#userbar-image-mode {
|
||||
font-weight: bold;
|
||||
margin-right: 1em;
|
||||
text-decoration: none;
|
||||
}
|
||||
/* line 146, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 149, ../../../app/stylesheets/_layout.sass */
|
||||
#userbar-image-mode img {
|
||||
bottom: -2px;
|
||||
height: 16px;
|
||||
|
@ -249,25 +252,25 @@ ul.buttons li, ul.buttons li form {
|
|||
width: 16px;
|
||||
}
|
||||
|
||||
/* line 149, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 152, ../../../app/stylesheets/_layout.sass */
|
||||
#userbar-log-in {
|
||||
text-decoration: none;
|
||||
}
|
||||
/* line 151, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 154, ../../../app/stylesheets/_layout.sass */
|
||||
#userbar-log-in img {
|
||||
margin-bottom: -4px;
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
/* line 155, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 158, ../../../app/stylesheets/_layout.sass */
|
||||
#userbar-log-in span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
/* line 157, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 160, ../../../app/stylesheets/_layout.sass */
|
||||
#userbar-log-in:hover span {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* line 160, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 163, ../../../app/stylesheets/_layout.sass */
|
||||
.object {
|
||||
display: -moz-inline-box;
|
||||
-moz-box-orient: vertical;
|
||||
|
@ -282,32 +285,32 @@ ul.buttons li, ul.buttons li form {
|
|||
vertical-align: top;
|
||||
width: 100px;
|
||||
}
|
||||
/* line 168, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 171, ../../../app/stylesheets/_layout.sass */
|
||||
.object a {
|
||||
text-decoration: none;
|
||||
}
|
||||
/* line 170, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 173, ../../../app/stylesheets/_layout.sass */
|
||||
.object a img {
|
||||
-moz-opacity: 0.75;
|
||||
-webkit-opacity: 0.75;
|
||||
-o-opacity: 0.75;
|
||||
-khtml-opacity: 0.75;
|
||||
}
|
||||
/* line 172, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 175, ../../../app/stylesheets/_layout.sass */
|
||||
.object img {
|
||||
display: block;
|
||||
height: 80px;
|
||||
margin: 0 auto;
|
||||
width: 80px;
|
||||
}
|
||||
/* line 177, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 180, ../../../app/stylesheets/_layout.sass */
|
||||
.object:hover img, .object a:hover img {
|
||||
-moz-opacity: 1;
|
||||
-webkit-opacity: 1;
|
||||
-o-opacity: 1;
|
||||
-khtml-opacity: 1;
|
||||
}
|
||||
/* line 183, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 186, ../../../app/stylesheets/_layout.sass */
|
||||
.object .nc-icon, .object .closeted-icons {
|
||||
-moz-opacity: 1;
|
||||
-webkit-opacity: 1;
|
||||
|
@ -318,7 +321,7 @@ ul.buttons li, ul.buttons li form {
|
|||
position: absolute;
|
||||
top: 64px;
|
||||
}
|
||||
/* line 189, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 192, ../../../app/stylesheets/_layout.sass */
|
||||
.object .nc-icon:hover, .object .closeted-icons:hover {
|
||||
-moz-opacity: 0.5;
|
||||
-webkit-opacity: 0.5;
|
||||
|
@ -326,32 +329,32 @@ ul.buttons li, ul.buttons li form {
|
|||
-khtml-opacity: 0.5;
|
||||
background: transparent;
|
||||
}
|
||||
/* line 193, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 196, ../../../app/stylesheets/_layout.sass */
|
||||
.object .nc-icon, .object .closeted-icons img {
|
||||
display: inline;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
/* line 198, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 201, ../../../app/stylesheets/_layout.sass */
|
||||
.object .nc-icon {
|
||||
right: 18px;
|
||||
}
|
||||
/* line 202, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 205, ../../../app/stylesheets/_layout.sass */
|
||||
.object .closeted-icons {
|
||||
left: 18px;
|
||||
}
|
||||
|
||||
/* line 205, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 208, ../../../app/stylesheets/_layout.sass */
|
||||
dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* line 208, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 211, ../../../app/stylesheets/_layout.sass */
|
||||
dd {
|
||||
margin: 0 0 1.5em 1em;
|
||||
}
|
||||
|
||||
/* line 211, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 214, ../../../app/stylesheets/_layout.sass */
|
||||
#home-link {
|
||||
font-family: Delicious, Helvetica, Arial, Verdana, sans-serif;
|
||||
font-size: 175%;
|
||||
|
@ -362,21 +365,21 @@ dd {
|
|||
position: absolute;
|
||||
top: 0;
|
||||
}
|
||||
/* line 221, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 224, ../../../app/stylesheets/_layout.sass */
|
||||
#home-link:hover {
|
||||
background: #eeffee;
|
||||
text-decoration: none;
|
||||
}
|
||||
/* line 224, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 227, ../../../app/stylesheets/_layout.sass */
|
||||
#home-link span:before {
|
||||
content: "<< ";
|
||||
}
|
||||
|
||||
/* line 228, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 231, ../../../app/stylesheets/_layout.sass */
|
||||
.pagination a, .pagination span {
|
||||
margin: 0 0.5em;
|
||||
}
|
||||
/* line 230, ../../../app/stylesheets/_layout.sass */
|
||||
/* line 233, ../../../app/stylesheets/_layout.sass */
|
||||
.pagination .current {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
@ -400,34 +403,6 @@ dd {
|
|||
src: local("Delicious"), url('/fonts/Delicious-Italic.otf');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Droid Serif";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
src: local("Droid Serif"), url("http://themes.googleusercontent.com/font?kit=70P0G8gxVDIV6F9om0DsKg") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Droid Serif";
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
src: local("Droid Serif"), url("http://themes.googleusercontent.com/font?kit=QQt14e8dY39u-eYBZmppwf5Jgr8ufe5A6KahQF76Xmg") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Droid Sans";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
src: local("Droid Sans"), url("http://themes.googleusercontent.com/font?kit=POVDFY-UUf0WFR9DIMCU8g") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Calligraffitti";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
src: local("Calligraffiti"), url("http://themes.googleusercontent.com/font?kit=vLVN2Y-z65rVu1R7lWdvyKIZAuDcNtpCWuPSaIR0Ie8") format("woff");
|
||||
}
|
||||
|
||||
/* line 2, ../../../app/stylesheets/partials/_jquery.jgrowl.sass */
|
||||
div.jGrowl {
|
||||
padding: 10px;
|
||||
|
|
BIN
vendor/cache/addressable-2.2.6.gem
vendored
BIN
vendor/cache/addressable-2.2.6.gem
vendored
Binary file not shown.
BIN
vendor/cache/addressable-2.3.2.gem
vendored
Normal file
BIN
vendor/cache/addressable-2.3.2.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/bullet-4.1.5.gem
vendored
BIN
vendor/cache/bullet-4.1.5.gem
vendored
Binary file not shown.
BIN
vendor/cache/bullet-4.1.6.gem
vendored
Normal file
BIN
vendor/cache/bullet-4.1.6.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/closure-compiler-1.1.4.gem
vendored
BIN
vendor/cache/closure-compiler-1.1.4.gem
vendored
Binary file not shown.
BIN
vendor/cache/closure-compiler-1.1.8.gem
vendored
Normal file
BIN
vendor/cache/closure-compiler-1.1.8.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/dye-0.1.4.gem
vendored
Normal file
BIN
vendor/cache/dye-0.1.4.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/em-socksify-0.1.0.gem
vendored
BIN
vendor/cache/em-socksify-0.1.0.gem
vendored
Binary file not shown.
BIN
vendor/cache/em-socksify-0.2.1.gem
vendored
Normal file
BIN
vendor/cache/em-socksify-0.2.1.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/excon-0.16.10.gem
vendored
Normal file
BIN
vendor/cache/excon-0.16.10.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/excon-0.9.6.gem
vendored
BIN
vendor/cache/excon-0.9.6.gem
vendored
Binary file not shown.
BIN
vendor/cache/factory_girl-2.3.2.gem
vendored
BIN
vendor/cache/factory_girl-2.3.2.gem
vendored
Binary file not shown.
BIN
vendor/cache/factory_girl-2.6.4.gem
vendored
Normal file
BIN
vendor/cache/factory_girl-2.6.4.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/factory_girl_rails-1.4.0.gem
vendored
BIN
vendor/cache/factory_girl_rails-1.4.0.gem
vendored
Binary file not shown.
BIN
vendor/cache/factory_girl_rails-1.7.0.gem
vendored
Normal file
BIN
vendor/cache/factory_girl_rails-1.7.0.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/fog-1.1.2.gem
vendored
BIN
vendor/cache/fog-1.1.2.gem
vendored
Binary file not shown.
BIN
vendor/cache/fog-1.8.0.gem
vendored
Normal file
BIN
vendor/cache/fog-1.8.0.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/formatador-0.2.1.gem
vendored
BIN
vendor/cache/formatador-0.2.1.gem
vendored
Binary file not shown.
BIN
vendor/cache/formatador-0.2.4.gem
vendored
Normal file
BIN
vendor/cache/formatador-0.2.4.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/globalize3-0.3.0.gem
vendored
Normal file
BIN
vendor/cache/globalize3-0.3.0.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/msgpack-0.4.6.gem
vendored
BIN
vendor/cache/msgpack-0.4.6.gem
vendored
Binary file not shown.
BIN
vendor/cache/msgpack-0.4.7.gem
vendored
Normal file
BIN
vendor/cache/msgpack-0.4.7.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/multi_json-1.0.4.gem
vendored
BIN
vendor/cache/multi_json-1.0.4.gem
vendored
Binary file not shown.
BIN
vendor/cache/multi_json-1.3.7.gem
vendored
Normal file
BIN
vendor/cache/multi_json-1.3.7.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/mysql2-0.2.18.gem
vendored
Normal file
BIN
vendor/cache/mysql2-0.2.18.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/mysql2-0.2.6.gem
vendored
BIN
vendor/cache/mysql2-0.2.6.gem
vendored
Binary file not shown.
BIN
vendor/cache/net-ssh-2.3.0.gem
vendored
BIN
vendor/cache/net-ssh-2.3.0.gem
vendored
Binary file not shown.
BIN
vendor/cache/net-ssh-2.6.3.gem
vendored
Normal file
BIN
vendor/cache/net-ssh-2.6.3.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/newrelic_rpm-3.5.3.25.gem
vendored
BIN
vendor/cache/newrelic_rpm-3.5.3.25.gem
vendored
Binary file not shown.
BIN
vendor/cache/newrelic_rpm-3.5.5.38.gem
vendored
Normal file
BIN
vendor/cache/newrelic_rpm-3.5.5.38.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/nokogiri-1.5.3.gem
vendored
BIN
vendor/cache/nokogiri-1.5.3.gem
vendored
Binary file not shown.
BIN
vendor/cache/nokogiri-1.5.6.gem
vendored
Normal file
BIN
vendor/cache/nokogiri-1.5.6.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/paper_trail-2.7.0.gem
vendored
Normal file
BIN
vendor/cache/paper_trail-2.7.0.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/parallel-0.5.17.gem
vendored
BIN
vendor/cache/parallel-0.5.17.gem
vendored
Binary file not shown.
BIN
vendor/cache/parallel-0.5.21.gem
vendored
Normal file
BIN
vendor/cache/parallel-0.5.21.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/patron-0.4.18.gem
vendored
Normal file
BIN
vendor/cache/patron-0.4.18.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/progressbar-0.11.0.gem
vendored
Normal file
BIN
vendor/cache/progressbar-0.11.0.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/prompter-0.1.5.gem
vendored
Normal file
BIN
vendor/cache/prompter-0.1.5.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/rack-1.2.6.gem
vendored
BIN
vendor/cache/rack-1.2.6.gem
vendored
Binary file not shown.
BIN
vendor/cache/rack-1.2.7.gem
vendored
Normal file
BIN
vendor/cache/rack-1.2.7.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/redis-2.2.2.gem
vendored
BIN
vendor/cache/redis-2.2.2.gem
vendored
Binary file not shown.
BIN
vendor/cache/redis-3.0.2.gem
vendored
Normal file
BIN
vendor/cache/redis-3.0.2.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/redis-namespace-1.1.0.gem
vendored
BIN
vendor/cache/redis-namespace-1.1.0.gem
vendored
Binary file not shown.
BIN
vendor/cache/redis-namespace-1.2.1.gem
vendored
Normal file
BIN
vendor/cache/redis-namespace-1.2.1.gem
vendored
Normal file
Binary file not shown.
BIN
vendor/cache/rufus-scheduler-2.0.16.gem
vendored
BIN
vendor/cache/rufus-scheduler-2.0.16.gem
vendored
Binary file not shown.
BIN
vendor/cache/rufus-scheduler-2.0.17.gem
vendored
Normal file
BIN
vendor/cache/rufus-scheduler-2.0.17.gem
vendored
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue