From 8e69d38ff726c6e07435f4894f484bd8a9f131b4 Mon Sep 17 00:00:00 2001 From: Matchu Date: Tue, 22 Jun 2010 12:42:25 -0400 Subject: [PATCH] refactoring search, removing database from set, fixing show.js to work with new swf --- app/models/item.rb | 91 ++++++++++++++++++++------------ app/models/species.rb | 6 +++ app/models/zone.rb | 11 +++- config/.gitignore | 1 + config/database.yml | 21 -------- config/item_zone_sets.yml | 0 public/javascripts/items/show.js | 17 +++--- 7 files changed, 81 insertions(+), 66 deletions(-) create mode 100644 config/.gitignore delete mode 100644 config/database.yml create mode 100644 config/item_zone_sets.yml diff --git a/app/models/item.rb b/app/models/item.rb index 02c26bf8..de342d43 100644 --- a/app/models/item.rb +++ b/app/models/item.rb @@ -11,11 +11,9 @@ class Item < ActiveRecord::Base scope :alphabetize, order('name ASC') - scope :occupying_zone, lambda { |zone_id| - joins('INNER JOIN parents_swf_assets psa ON psa.swf_asset_type = "object" AND psa.parent_id = objects.id'). - joins('INNER JOIN swf_assets sa ON sa.id = psa.swf_asset_id'). - where('sa.zone_id = ?', zone_id) - } + scope :join_swf_assets, joins('INNER JOIN parents_swf_assets psa ON psa.swf_asset_type = "object" AND psa.parent_id = objects.id'). + joins('INNER JOIN swf_assets ON swf_assets.id = psa.swf_asset_id'). + group('objects.id') # Not defining validations, since this app is currently read-only @@ -45,23 +43,66 @@ class Item < ActiveRecord::Base elsif c == '"' in_phrase = !in_phrase elsif c == ':' && !in_phrase - query_conditions.last.to_property! + query_conditions.last.to_filter! elsif c == '-' && !in_phrase && query_conditions.last.empty? query_conditions.last.negate! else query_conditions.last << c end end - query_conditions.inject(self) do |scope, condition| + query_conditions.inject(self.scoped) do |scope, condition| condition.narrow(scope) end end private + SearchFilterScopes = [] + + def self.search_filter(name, args={}) + SearchFilterScopes << name.to_s + scope "search_filter_#{name}", lambda { |str, negative| + condition = yield(str) + condition = condition.not if negative + rel = where(condition) + rel = rel & args[:scope] if args[:scope] + rel + } + end + + search_filter :name do |name| + arel_table[:name].matches("%#{name}%") + end + + search_filter :description do |description| + arel_table[:description].matches("%#{description}%") + end + + search_filter :only do |species_name| + id = Species.require_by_name(species_name).id + arel_table[:species_support_ids].eq(id.to_s) + end + + search_filter :species do |species_name| + id = Species.require_by_name(species_name).id + ids = arel_table[:species_support_ids] + ids.eq('').or(ids.matches_any( + id, + "#{id},%", + "%,#{id},%", + "%,#{id}" + )) + end + + search_filter :type, {:scope => join_swf_assets} do |zone_set_name| + zone_set = Zone::ItemZoneSets[zone_set_name] + raise ArgumentError, "Type \"#{zone_set_name}\" does not exist" unless zone_set + SwfAsset.arel_table[:zone_id].in(zone_set.map(&:id)) + end + class Condition < String - def to_property! - @property = self.clone + def to_filter! + @filter = self.clone self.replace '' end @@ -70,35 +111,19 @@ class Item < ActiveRecord::Base end def narrow(scope) - items = Table(:objects) - if @property == 'species' || @property == 'only' - species = Species.find_by_name(self) - raise ArgumentError, "Species \"#{self.humanize}\" does not exist" unless species - # TODO: add a many-to-many table to handle this relationship, if - # performance becomes an issue - ids = items[:species_support_ids] - if @property == 'species' - condition = ids.eq('').or(ids.matches_any( - species.id, - "#{species.id},%", - "%,#{species.id},%", - "%,#{species.id}" - )) - else - condition = items[:species_support_ids].eq(species.id.to_s) - end - elsif @property == 'description' || @property.blank? - column = @property == 'description' ? :description : :name - condition = items[column].matches("%#{self}%") + if SearchFilterScopes.include?(filter) + scope & Item.send("search_filter_#{filter}", self, @negative) else - raise ArgumentError, "Unknown search filter \"#{@property}\"" + raise ArgumentError, "Filter #{filter} does not exist" end - condition = condition.not if @negative - scope.where(condition) + end + + def filter + @filter || 'name' end def inspect - @property ? "#{@property}:#{super}" : super + @filter ? "#{@filter}:#{super}" : super end end end diff --git a/app/models/species.rb b/app/models/species.rb index 367e1c8d..ccb4b342 100644 --- a/app/models/species.rb +++ b/app/models/species.rb @@ -1,3 +1,9 @@ class Species < PetAttribute fetch_objects! + + def self.require_by_name(name) + species = Species.find_by_name(name) + raise ArgumentError, "Species \"#{name.humanize}\" does not exist" unless species + species + end end diff --git a/app/models/zone.rb b/app/models/zone.rb index 1f70bc59..ef74a894 100644 --- a/app/models/zone.rb +++ b/app/models/zone.rb @@ -1,5 +1,6 @@ class Zone < StaticResource - AttributeNames = ['id', 'label', 'depth'] + AttributeNames = ['id', 'label', 'depth', 'type_id'] + ItemZoneSets = {} attr_reader *AttributeNames @@ -12,7 +13,13 @@ class Zone < StaticResource n = 0 @objects = YAML.load_file(Rails.root.join('config', 'zones.yml')).map do |a| a['id'] = (n += 1) - new(a) + obj = new(a) + if obj.type_id == 2 || obj.type_id == 3 + zone_name = obj.label.delete(' -').gsub(/item$/, '').downcase + ItemZoneSets[zone_name] ||= [] + ItemZoneSets[zone_name] << obj + end + obj end n = nil end diff --git a/config/.gitignore b/config/.gitignore new file mode 100644 index 00000000..b5649dd0 --- /dev/null +++ b/config/.gitignore @@ -0,0 +1 @@ +database.yml diff --git a/config/database.yml b/config/database.yml deleted file mode 100644 index 1dd896f5..00000000 --- a/config/database.yml +++ /dev/null @@ -1,21 +0,0 @@ -development: - adapter: mysql - encoding: utf8 - database: wearables - pool: 5 - username: wearables - -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. -test: - adapter: sqlite3 - database: db/test.sqlite3 - pool: 5 - timeout: 5000 - -production: - adapter: sqlite3 - database: db/production.sqlite3 - pool: 5 - timeout: 5000 diff --git a/config/item_zone_sets.yml b/config/item_zone_sets.yml new file mode 100644 index 00000000..e69de29b diff --git a/public/javascripts/items/show.js b/public/javascripts/items/show.js index 942dcd7e..7fdcc910 100644 --- a/public/javascripts/items/show.js +++ b/public/javascripts/items/show.js @@ -42,7 +42,7 @@ function PetType() { var pet_type = this, loaded_data = false, loaded_assets = false; this.activated = true; - this.assets = true; + this.assets = []; this.deactivate = function (error, args) { var msg; @@ -182,20 +182,17 @@ Item.createFromLocation = function () { Preview = new function Preview() { var swf_id, swf, updateWhenFlashReady = false; - this.setFlashIsReady = function () { + window.previewSWFIsReady = function () { swf = document.getElementById(swf_id); if(updateWhenFlashReady) this.update(); } this.update = function (assets) { - var assets = [], asset_sources = [ - PetType.current.assets, - Item.current.getAssetsForPetType(PetType.current) - ]; + var assets; if(swf) { - $.each(asset_sources, function () { - assets = assets.concat(this); - }); + assets = PetType.current.assets.concat( + Item.current.getAssetsForPetType(PetType.current) + ); assets = $.grep(assets, function (asset) { var visible = $.inArray(asset.zone_id, Item.current.restricted_zones) == -1; if(visible) asset.local_path = asset.local_url; @@ -249,4 +246,4 @@ speciesList.each(function () { setTimeout($.proxy(Item.current, 'loadAllStandard'), 5000); -MainWardrobe = { View: { Outfit: Preview } }; +var SWFLog = $.noop;