impress/app/models/item/search/query.rb

127 lines
3 KiB
Ruby
Raw Normal View History

# encoding=utf-8
# ^ to put the regex in utf-8 mode
class Item
module Search
class Query
def initialize(filters, user, text=nil)
@filters = filters
2013-01-22 21:52:34 -08:00
@user = user
@text = text
end
def results
@filters.map(&:to_query).inject(Item.all, &:merge).
alphabetize_by_translations(Query.locale)
end
def to_s
@text || @filters.map(&:to_s).join(' ')
end
def self.locale
(I18n.fallbacks[I18n.locale] &
I18n.locales_with_neopets_language_code).first
end
TEXT_FILTER_EXPR = /([+-]?)(?:(\p{Word}+):)?(?:"([^"]+)"|(\S+))/
def self.from_text(text, user=nil)
filters = []
2013-01-22 21:52:34 -08:00
text.scan(TEXT_FILTER_EXPR) do |sign, key, quoted_value, unquoted_value|
key = 'name' if key.blank?
value = quoted_value || unquoted_value
is_positive = (sign != '-')
case key
when 'name'
filters << NameFilter.new(value, locale, is_positive)
when 'is'
case value
when 'nc'
filters << NCFilter.new(is_positive)
when 'np'
filters << NPFilter.new(is_positive)
else
message = I18n.translate('items.search.errors.not_found.label',
:label => value)
raise Item::Search::Error, message
end
else
message = I18n.translate('items.search.errors.not_found.label',
:label => key)
raise Item::Search::Error, message
end
end
self.new(filters, user, text)
end
def self.from_params(params, user=nil)
raise NotImplementedError, "TODO: Reimplemented Advanced Search"
end
end
2014-04-02 18:26:53 -07:00
class Error < Exception
end
2014-04-02 18:26:53 -07:00
private
class NameFilter
def initialize(value, locale, is_positive)
@value = value
@locale = locale
@is_positive = is_positive
end
def to_query
base = Item.joins(:translations).where('locale = ?', @locale)
if @is_positive
base.where('name LIKE ?', '%' + Item.sanitize_sql_like(@value) + '%')
else
base.where('name NOT LIKE ?', '%' + Item.sanitize_sql_like(@value) + '%')
end
end
def to_s
sign = @is_positive ? '' : '-'
if /\s/.match(@value)
sign + '"' + @value + '"'
else
sign + @value
end
end
end
class NCFilter
def initialize(is_positive)
@is_positive = is_positive
end
def to_query
@is_positive ? Item.is_nc : Item.is_np
end
def to_s
sign = @is_positive ? '' : '-'
sign + 'is:nc'
end
end
class NPFilter
def initialize(is_positive)
@is_positive = is_positive
end
def to_query
@is_positive ? Item.is_np : Item.is_nc
end
def to_s
sign = @is_positive ? '' : '-'
sign + 'is:np'
end
end
end
end