From 170b7fa6f52079e5df10608d832a024c3573ca7b Mon Sep 17 00:00:00 2001 From: Matchu Date: Wed, 26 Feb 2014 23:55:14 -0600 Subject: [PATCH] can search items with a form-based query instead of text-based --- app/controllers/items_controller.rb | 19 ++++++++++++------- app/models/item/search/filter.rb | 16 ++++++++++++++++ app/models/item/search/query.rb | 20 +++++++++++++++++++- 3 files changed, 47 insertions(+), 8 deletions(-) diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb index 1a43e021..d70c483e 100644 --- a/app/controllers/items_controller.rb +++ b/app/controllers/items_controller.rb @@ -3,7 +3,7 @@ class ItemsController < ApplicationController rescue_from Item::Search::Error, :with => :search_error def index - if params.has_key?(:q) + if @query begin if params[:per_page] per_page = params[:per_page].to_i @@ -13,8 +13,7 @@ class ItemsController < ApplicationController end # Note that we sort by name by hand, since we might have to use # fallbacks after the fact - @items = Item::Search::Query.from_text(@query, current_user). - paginate(page: params[:page], per_page: per_page) + @items = @query.paginate(page: params[:page], per_page: per_page) assign_closeted! respond_to do |format| format.html { @@ -27,11 +26,13 @@ class ItemsController < ApplicationController } format.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 { @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] } end @@ -149,7 +150,11 @@ class ItemsController < ApplicationController end 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 - diff --git a/app/models/item/search/filter.rb b/app/models/item/search/filter.rb index 0f54c5b0..29ff5d17 100644 --- a/app/models/item/search/filter.rb +++ b/app/models/item/search/filter.rb @@ -12,6 +12,22 @@ class Item def positive? @is_positive 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 diff --git a/app/models/item/search/query.rb b/app/models/item/search/query.rb index 627b4ea5..c1291601 100644 --- a/app/models/item/search/query.rb +++ b/app/models/item/search/query.rb @@ -13,6 +13,7 @@ class Item :name => Fields::SetField, :user_closet_hanger_ownership => Fields::SetField } + FIELD_KEYS = FIELD_CLASSES.keys def initialize(filters, user) @filters = filters @@ -108,7 +109,7 @@ class Item OWNERSHIP_KEYWORDS[locale] = {} 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 # commas: "occupies,zone,type" labels = I18n.translate("items.search.labels.#{key}", @@ -131,6 +132,10 @@ class Item end end end + + def to_s + @filters.map(&:to_s).join(' ') + end TEXT_QUERY_RESOURCE_FINDERS = { :species => lambda { |name| @@ -219,6 +224,19 @@ class Item self.new(filters, user) 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