93 lines
2.9 KiB
Ruby
93 lines
2.9 KiB
Ruby
class Item < ActiveRecord::Base
|
|
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
|
|
|
|
has_many :parent_swf_asset_relationships, :foreign_key => 'parent_id'
|
|
has_many :swf_assets, :through => :parent_swf_asset_relationships
|
|
|
|
scope :alphabetize, order('name ASC')
|
|
|
|
# Not defining validations, since this app is currently read-only
|
|
|
|
def species_support_ids
|
|
@species_support_ids_array ||= read_attribute('species_support_ids').split(',').map(&:to_i)
|
|
end
|
|
|
|
def species_support_ids=(replacement)
|
|
@species_support_ids_array = nil
|
|
replacement = replacement.join(',') if replacement.is_a?(Array)
|
|
write_attribute('species_support_ids', replacement)
|
|
end
|
|
|
|
def supported_species
|
|
@supported_species ||= species_support_ids.empty? ? Species.all : species_support_ids.map { |id| Species.find(id) }
|
|
end
|
|
|
|
def self.search(query)
|
|
raise ArgumentError, "Please provide a search query" unless query
|
|
query = query.strip
|
|
raise ArgumentError, "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_property!
|
|
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|
|
|
condition.narrow(scope)
|
|
end
|
|
end
|
|
|
|
private
|
|
|
|
class Condition < String
|
|
def to_property!
|
|
@property = self.clone
|
|
self.replace ''
|
|
end
|
|
|
|
def negate!
|
|
@negative = true
|
|
end
|
|
|
|
def narrow(scope)
|
|
items = Table(:objects)
|
|
if @property == 'species'
|
|
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]
|
|
condition = ids.eq('').or(ids.matches_any(
|
|
species.id,
|
|
"#{species.id},%",
|
|
"%,#{species.id},%",
|
|
"%,#{species.id}"
|
|
))
|
|
elsif @property == 'description' || @property.blank?
|
|
column = @property == 'description' ? :description : :name
|
|
condition = items[column].matches("%#{self}%")
|
|
else
|
|
raise ArgumentError, "Unknown search filter \"#{@property}\""
|
|
end
|
|
condition = condition.not if @negative
|
|
scope.where(condition)
|
|
end
|
|
|
|
def inspect
|
|
@property ? "#{@property}:#{super}" : super
|
|
end
|
|
end
|
|
end
|