user:owns, user:wants queries

This commit is contained in:
Emi Matchu 2013-01-22 23:52:34 -06:00
parent dd30fbe0d7
commit 7f18fe12c1
5 changed files with 90 additions and 14 deletions

View file

@ -5,6 +5,11 @@
# 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>>
@ -14,18 +19,22 @@ ANCHORS:
- &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:
multi_match:
query: <<name>>
fields: <<fields>>
type: phrase
*name_partial
_negative_names:
multi_match:
query: <<name>>
fields: <<fields>>
type: phrase
*name_partial
_species_support_ids:
*species_support_id_partial
@ -45,6 +54,12 @@ _restricted_zone_ids:
_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:
@ -57,10 +72,12 @@ item_search:
- <<_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

View file

@ -1,4 +1,6 @@
class ClosetHanger < ActiveRecord::Base
include Flex::Model
belongs_to :item
belongs_to :list, :class_name => 'ClosetList'
belongs_to :user
@ -29,6 +31,17 @@ class ClosetHanger < ActiveRecord::Base
end
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?)

View file

@ -7,11 +7,13 @@ class Item
:species_support_id => Fields::SetField,
:occupied_zone_id => Fields::SetField,
:restricted_zone_id => Fields::SetField,
:name => Fields::SetField
:name => Fields::SetField,
:user_closet_hanger_ownership => Fields::SetField
}
def initialize(filters, user)
@filters = filters
@user = user
end
def fields
@ -35,7 +37,8 @@ class Item
final_flex_params = {
:page => (options[:page] || 1),
:size => (options[:per_page] || 30)
:size => (options[:per_page] || 30),
:type => 'item'
}.merge(flex_params)
locales = I18n.fallbacks[I18n.locale] &
@ -64,6 +67,19 @@ class Item
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)}
@ -73,14 +89,22 @@ class Item
# 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
@ -98,27 +122,40 @@ class Item
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
: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'
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.
# 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

View file

@ -3,7 +3,7 @@
Flex::Configuration.configure do |config|
# you MUST add your indexed model names here
config.flex_models = %w[ Item ]
config.flex_models = %w[ Item ClosetHanger ]
# Add the your result extenders here
config.result_extenders |= [ FlexSearchExtender ]

View file

@ -333,6 +333,12 @@ en:
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
@ -340,6 +346,9 @@ en:
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: