forked from OpenNeo/impress
user:owns, user:wants queries
This commit is contained in:
parent
dd30fbe0d7
commit
7f18fe12c1
5 changed files with 90 additions and 14 deletions
|
@ -5,6 +5,11 @@
|
||||||
# ANCHORS litheral key: it will not be used as template
|
# ANCHORS litheral key: it will not be used as template
|
||||||
# you can store here fragments of queries to reuse in the templates below
|
# you can store here fragments of queries to reuse in the templates below
|
||||||
ANCHORS:
|
ANCHORS:
|
||||||
|
- &name_partial
|
||||||
|
multi_match:
|
||||||
|
query: <<name>>
|
||||||
|
fields: <<fields>>
|
||||||
|
type: phrase
|
||||||
- &species_support_id_partial
|
- &species_support_id_partial
|
||||||
term:
|
term:
|
||||||
species_support_id: <<species_support_id>>
|
species_support_id: <<species_support_id>>
|
||||||
|
@ -14,18 +19,22 @@ ANCHORS:
|
||||||
- &restricted_zone_id_partial
|
- &restricted_zone_id_partial
|
||||||
terms:
|
terms:
|
||||||
restricted_zone_id: <<restricted_zone_id>>
|
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:
|
_names:
|
||||||
multi_match:
|
*name_partial
|
||||||
query: <<name>>
|
|
||||||
fields: <<fields>>
|
|
||||||
type: phrase
|
|
||||||
|
|
||||||
_negative_names:
|
_negative_names:
|
||||||
multi_match:
|
*name_partial
|
||||||
query: <<name>>
|
|
||||||
fields: <<fields>>
|
|
||||||
type: phrase
|
|
||||||
|
|
||||||
_species_support_ids:
|
_species_support_ids:
|
||||||
*species_support_id_partial
|
*species_support_id_partial
|
||||||
|
@ -45,6 +54,12 @@ _restricted_zone_ids:
|
||||||
_negative_restricted_zone_ids:
|
_negative_restricted_zone_ids:
|
||||||
*restricted_zone_id_partial
|
*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:
|
item_search:
|
||||||
- query:
|
- query:
|
||||||
bool:
|
bool:
|
||||||
|
@ -57,10 +72,12 @@ item_search:
|
||||||
- <<_species_support_ids= ~>>
|
- <<_species_support_ids= ~>>
|
||||||
- <<_occupied_zone_ids= ~>>
|
- <<_occupied_zone_ids= ~>>
|
||||||
- <<_restricted_zone_ids= ~>>
|
- <<_restricted_zone_ids= ~>>
|
||||||
|
- <<_user_closet_hanger_ownerships= ~>>
|
||||||
must_not:
|
must_not:
|
||||||
- <<_negative_names= ~>>
|
- <<_negative_names= ~>>
|
||||||
- <<_negative_species_support_ids= ~>>
|
- <<_negative_species_support_ids= ~>>
|
||||||
- <<_negative_occupied_zone_ids= ~>>
|
- <<_negative_occupied_zone_ids= ~>>
|
||||||
- <<_negative_restricted_zone_ids= ~>>
|
- <<_negative_restricted_zone_ids= ~>>
|
||||||
|
- <<_negative_user_closet_hanger_ownerships= ~>>
|
||||||
sort:
|
sort:
|
||||||
- name.<<locale>>.untouched
|
- name.<<locale>>.untouched
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
class ClosetHanger < ActiveRecord::Base
|
class ClosetHanger < ActiveRecord::Base
|
||||||
|
include Flex::Model
|
||||||
|
|
||||||
belongs_to :item
|
belongs_to :item
|
||||||
belongs_to :list, :class_name => 'ClosetList'
|
belongs_to :list, :class_name => 'ClosetList'
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
|
@ -30,6 +32,17 @@ class ClosetHanger < ActiveRecord::Base
|
||||||
|
|
||||||
before_validation :merge_quantities, :set_owned_by_list
|
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)
|
def verb(subject=:someone)
|
||||||
self.class.verb(subject, owned?)
|
self.class.verb(subject, owned?)
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,11 +7,13 @@ class Item
|
||||||
:species_support_id => Fields::SetField,
|
:species_support_id => Fields::SetField,
|
||||||
:occupied_zone_id => Fields::SetField,
|
:occupied_zone_id => Fields::SetField,
|
||||||
:restricted_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)
|
def initialize(filters, user)
|
||||||
@filters = filters
|
@filters = filters
|
||||||
|
@user = user
|
||||||
end
|
end
|
||||||
|
|
||||||
def fields
|
def fields
|
||||||
|
@ -35,7 +37,8 @@ class Item
|
||||||
|
|
||||||
final_flex_params = {
|
final_flex_params = {
|
||||||
:page => (options[:page] || 1),
|
:page => (options[:page] || 1),
|
||||||
:size => (options[:per_page] || 30)
|
:size => (options[:per_page] || 30),
|
||||||
|
:type => 'item'
|
||||||
}.merge(flex_params)
|
}.merge(flex_params)
|
||||||
|
|
||||||
locales = I18n.fallbacks[I18n.locale] &
|
locales = I18n.fallbacks[I18n.locale] &
|
||||||
|
@ -64,6 +67,19 @@ class Item
|
||||||
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 = FlexSearch.item_search(final_flex_params)
|
||||||
result.scoped_loaded_collection(
|
result.scoped_loaded_collection(
|
||||||
:scopes => {'Item' => Item.includes(:translations)}
|
:scopes => {'Item' => Item.includes(:translations)}
|
||||||
|
@ -73,14 +89,22 @@ class Item
|
||||||
# Load the text query labels from I18n, so that when we see, say,
|
# Load the text query labels from I18n, so that when we see, say,
|
||||||
# the filter "species:acara", we know it means species_support_id.
|
# the filter "species:acara", we know it means species_support_id.
|
||||||
TEXT_KEYS_BY_LABEL = {}
|
TEXT_KEYS_BY_LABEL = {}
|
||||||
|
OWNERSHIP_KEYWORDS = {}
|
||||||
I18n.available_locales.each do |locale|
|
I18n.available_locales.each do |locale|
|
||||||
TEXT_KEYS_BY_LABEL[locale] = {}
|
TEXT_KEYS_BY_LABEL[locale] = {}
|
||||||
|
OWNERSHIP_KEYWORDS[locale] = {}
|
||||||
FIELD_CLASSES.keys.each do |key|
|
FIELD_CLASSES.keys.each do |key|
|
||||||
# A locale can specify multiple labels for a key by separating by
|
# A locale can specify multiple labels for a key by separating by
|
||||||
# commas: "occupies,zone,type"
|
# commas: "occupies,zone,type"
|
||||||
labels = I18n.translate("items.search.labels.#{key}",
|
labels = I18n.translate("items.search.labels.#{key}",
|
||||||
:locale => locale).split(',')
|
:locale => locale).split(',')
|
||||||
labels.each { |label| TEXT_KEYS_BY_LABEL[locale][label] = key }
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -98,27 +122,40 @@ class Item
|
||||||
Item::Search.error 'not_found.zone', :zone_name => name
|
Item::Search.error 'not_found.zone', :zone_name => name
|
||||||
end
|
end
|
||||||
zone_set.map(&:id)
|
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 = {
|
TEXT_QUERY_RESOURCE_TYPES_BY_KEY = {
|
||||||
:species_support_id => :species,
|
:species_support_id => :species,
|
||||||
:occupied_zone_id => :zone,
|
:occupied_zone_id => :zone,
|
||||||
:restricted_zone_id => :zone
|
:restricted_zone_id => :zone,
|
||||||
|
:user_closet_hanger_ownership => :ownership
|
||||||
}
|
}
|
||||||
|
|
||||||
TEXT_FILTER_EXPR = /([+-]?)(?:([a-z]+):)?(?:"([^"]+)"|(\S+))/
|
TEXT_FILTER_EXPR = /([+-]?)(?:([a-z]+):)?(?:"([^"]+)"|(\S+))/
|
||||||
def self.from_text(text, user=nil)
|
def self.from_text(text, user=nil)
|
||||||
filters = []
|
filters = []
|
||||||
|
|
||||||
|
is_keyword = I18n.translate('items.search.flag_keywords.is')
|
||||||
text.scan(TEXT_FILTER_EXPR) do |sign, label, quoted_value, unquoted_value|
|
text.scan(TEXT_FILTER_EXPR) do |sign, label, quoted_value, unquoted_value|
|
||||||
label ||= 'name'
|
label ||= 'name'
|
||||||
raw_value = quoted_value || unquoted_value
|
raw_value = quoted_value || unquoted_value
|
||||||
is_positive = (sign != '-')
|
is_positive = (sign != '-')
|
||||||
|
|
||||||
if label == 'is'
|
if label == is_keyword
|
||||||
# is-filters are weird. "-is:nc" is transposed to something more
|
# is-filters are weird. "-is:nc" is transposed to something more
|
||||||
# like "-nc:<nil>", then it's translated into a negative "is_nc"
|
# 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
|
label = raw_value
|
||||||
raw_value = nil
|
raw_value = nil
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
Flex::Configuration.configure do |config|
|
Flex::Configuration.configure do |config|
|
||||||
|
|
||||||
# you MUST add your indexed model names here
|
# 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
|
# Add the your result extenders here
|
||||||
config.result_extenders |= [ FlexSearchExtender ]
|
config.result_extenders |= [ FlexSearchExtender ]
|
||||||
|
|
|
@ -333,6 +333,12 @@ en:
|
||||||
species:
|
species:
|
||||||
Species "%{species_name}" does not exist. Is it spelled correctly?
|
Species "%{species_name}" does not exist. Is it spelled correctly?
|
||||||
zone: Zone "%{zone_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:
|
labels:
|
||||||
name: name
|
name: name
|
||||||
is_nc: nc
|
is_nc: nc
|
||||||
|
@ -340,6 +346,9 @@ en:
|
||||||
species_support_id: species
|
species_support_id: species
|
||||||
occupied_zone_id: occupies,zone,type
|
occupied_zone_id: occupies,zone,type
|
||||||
restricted_zone_id: restricts
|
restricted_zone_id: restricts
|
||||||
|
user_closet_hanger_ownership: user
|
||||||
|
user_owns: owns
|
||||||
|
user_wants: wants
|
||||||
|
|
||||||
neopets_pages:
|
neopets_pages:
|
||||||
create:
|
create:
|
||||||
|
|
Loading…
Reference in a new issue