can search items with a form-based query instead of text-based

This commit is contained in:
Emi Matchu 2014-02-26 23:55:14 -06:00
parent a326f09eda
commit 170b7fa6f5
3 changed files with 47 additions and 8 deletions

View file

@ -3,7 +3,7 @@ class ItemsController < ApplicationController
rescue_from Item::Search::Error, :with => :search_error rescue_from Item::Search::Error, :with => :search_error
def index def index
if params.has_key?(:q) if @query
begin begin
if params[:per_page] if params[:per_page]
per_page = params[:per_page].to_i per_page = params[:per_page].to_i
@ -13,8 +13,7 @@ class ItemsController < ApplicationController
end end
# Note that we sort by name by hand, since we might have to use # Note that we sort by name by hand, since we might have to use
# fallbacks after the fact # fallbacks after the fact
@items = Item::Search::Query.from_text(@query, current_user). @items = @query.paginate(page: params[:page], per_page: per_page)
paginate(page: params[:page], per_page: per_page)
assign_closeted! assign_closeted!
respond_to do |format| respond_to do |format|
format.html { format.html {
@ -27,11 +26,13 @@ class ItemsController < ApplicationController
} }
format.json { format.json {
@items.prepare_method(:as_json) @items.prepare_method(:as_json)
render json: {items: @items, total_pages: @items.total_pages} render json: {items: @items, total_pages: @items.total_pages,
query: @query.to_s}
} }
format.js { format.js {
@items.prepare_method(:as_json) @items.prepare_method(:as_json)
render json: {items: @items, total_pages: @items.total_pages}, render json: {items: @items, total_pages: @items.total_pages,
query: @query.to_s},
callback: params[:callback] callback: params[:callback]
} }
end end
@ -149,7 +150,11 @@ class ItemsController < ApplicationController
end end
def set_query def set_query
@query = params[:q] q = params[:q]
if q.is_a?(String)
@query = Item::Search::Query.from_text(q, current_user)
elsif q.is_a?(Hash)
@query = Item::Search::Query.from_params(q, current_user)
end
end end
end end

View file

@ -12,6 +12,22 @@ class Item
def positive? def positive?
@is_positive @is_positive
end end
def to_s
sign = positive? ? '' : '-'
key_str = key.to_s
if key_str.start_with?('is_')
rest_of_key = key_str[3..-1]
"#{sign}is:#{rest_of_key}"
else
quoted_value = value.include?(' ') ? value.inspect : value
if key == :name
"#{sign}#{quoted_value}"
else
"#{sign}#{key}:#{quoted_value}"
end
end
end
end end
end end
end end

View file

@ -13,6 +13,7 @@ class Item
:name => Fields::SetField, :name => Fields::SetField,
:user_closet_hanger_ownership => Fields::SetField :user_closet_hanger_ownership => Fields::SetField
} }
FIELD_KEYS = FIELD_CLASSES.keys
def initialize(filters, user) def initialize(filters, user)
@filters = filters @filters = filters
@ -108,7 +109,7 @@ class Item
OWNERSHIP_KEYWORDS[locale] = {} OWNERSHIP_KEYWORDS[locale] = {}
I18n.fallbacks[locale].each do |fallback| I18n.fallbacks[locale].each do |fallback|
FIELD_CLASSES.keys.each do |key| FIELD_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}",
@ -132,6 +133,10 @@ class Item
end end
end end
def to_s
@filters.map(&:to_s).join(' ')
end
TEXT_QUERY_RESOURCE_FINDERS = { TEXT_QUERY_RESOURCE_FINDERS = {
:species => lambda { |name| :species => lambda { |name|
species = Species.find_by_name(name) species = Species.find_by_name(name)
@ -220,6 +225,19 @@ class Item
self.new(filters, user) self.new(filters, user)
end end
def self.from_params(params, user=nil)
filters = params.values.map { |filter_params|
if filter_params.has_key?(:key)
key = filter_params[:key].to_sym
if FIELD_KEYS.include?(key)
Filter.new(key, filter_params[:value], filter_params[:is_positive] == 'true')
end
end
}.compact
self.new(filters, user)
end
private private
# The fields start out empty, then have the filters inserted into 'em, # The fields start out empty, then have the filters inserted into 'em,