lib/inquisitio/searcher.rb in inquisitio-0.0.12 vs lib/inquisitio/searcher.rb in inquisitio-0.0.13

- old
+ new

@@ -1,49 +1,134 @@ require 'excon' +require "deep_clone" module Inquisitio class Searcher - def self.search(*args) - searcher = new(*args) - searcher.search - searcher + def self.method_missing(name, *args) + Searcher.new.send(name, *args) end - attr_reader :results - def initialize(query, filters = {}) - raise InquisitioError.new("Query is null") if query.nil? + attr_reader :params + def initialize(params = nil) + @params = params || { + criteria: [], + filters: {}, + per: 10, + page: 1, + returns: [], + with: {} + } - if query.is_a?(String) - @query = query - @filters = filters - else - @filters = query - end - - @return_fields = @filters.delete(:return_fields) - @arguments = @filters.delete(:arguments) + yield(self) if block_given? end def search - response = Excon.get(search_url) - raise InquisitioError.new("Search failed with status code: #{response.status} Message #{response.body}") unless response.status == 200 - body = response.body - @results = JSON.parse(body)["hits"]["hit"] + results end def ids - @ids ||= @results.map{|result|result['id']} + @ids ||= map{|r|r['med_id']} end def records - @records ||= @results.map do |result| - {result['type'] => result['id']} + @records ||= begin + klasses = {} + map do |result| + klass = result['med_type'] + klasses[klass] ||= [] + klasses[klass] << result['med_id'] + end + + klasses.map {|klass, ids| + klass.constantize.where(id: ids) + }.flatten end end + def where(value) + clone do |s| + if value.is_a?(Array) + s.params[:criteria] += value + elsif value.is_a?(Hash) + value.each do |k,v| + s.params[:filters][k] ||= [] + if v.is_a?(Array) + s.params[:filters][k] = v + else + s.params[:filters][k] << v + end + end + else + s.params[:criteria] << value + end + end + end + + def per(value) + clone do |s| + s.params[:per] = value.to_i + end + end + + def page(value) + clone do |s| + s.params[:page] = value.to_i + end + end + + def returns(*value) + clone do |s| + if value.is_a?(Array) + s.params[:returns] += value + else + s.params[:returns] << value + end + end + end + + def with(value) + clone do |s| + s.params[:with].merge!(value) + end + end + + # Proxy everything to the results so that this this class + # transparently acts as an Array. + def method_missing(name, *args, &block) + results.to_a.send(name, *args, &block) + end + private + + def results + if @results.nil? + response = Excon.get(search_url) + raise InquisitioError.new("Search failed with status code: #{response.status} Message #{response.body}") unless response.status == 200 + @results = JSON.parse(response.body)["hits"]["hit"] + end + @results + end + def search_url - @search_url ||= SearchUrlBuilder.build(query: @query, filters: @filters, arguments: @arguments, return_fields: @return_fields) + @search_url ||= begin + return_fields = params[:returns].empty?? [:med_type, :med_id] : params[:returns] + + SearchUrlBuilder.build( + query: params[:criteria], + filters: params[:filters], + arguments: params[:with].merge({ + size: params[:per], + start: params[:per] * params[:page] + }), + return_fields: return_fields + ) + end + end + + def clone + Searcher.new(DeepClone.clone(params)) do |s| + yield(s) if block_given? + end end end end