lib/services/search.rb in Active-0.0.6 vs lib/services/search.rb in Active-0.0.7

- old
+ new

@@ -27,16 +27,178 @@ "activities" end end class Search - # attr_accessor :location, :category, :channels, :daterange, :keywords, :radius, :limit, :sort, :page, :offset, - # :asset_type_id, :api_key, :num_results, :view, :facet, :sort - # + attr_accessor :api_key, :start_date, :end_date, :location, :channels, :keywords, :search, :radius, :limit, :sort, :page, :offset, + :view, :facet, :sort, :num_results + + attr_reader :results, :endIndex, :pageSize, :searchTime, :numberOfResults, :end_point, :meta + SEARCH_URL = "http://search.active.com" DEFAULT_TIMEOUT = 5 + + def initialize(data={}) + self.api_key = data[:api_key] || "" + self.location = data[:location] || "" + self.channels = data[:channels] || [] + self.keywords = data[:keywords] || [] + self.radius = data[:radius] || "50" + self.limit = data[:limit] || "10" + self.sort = data[:sort] || Sort.DATE_ASC + self.page = data[:page] || "1" + self.offset = data[:offset] || "0" + self.view = data[:view] || "json" + self.facet = data[:facet] || Facet.ACTIVITIES + self.num_results = data[:num_results] || "10" + self.search = data[:search] || "" + self.start_date = data[:start_date] || "today" + self.end_date = data[:end_date] || "+" + + # Search.construct_url + end + + def location=(value) + @location = CGI.escape(value) + end + + def keywords=(value) + if value.class == String + @keywords = value.split(",").each { |k| k.strip! } + else + @keywords = value + end + end + + def channels=(value) + if value.class == String + @channels = value.split(",").each { |k| k.strip! } + else + @channels = value + end + end + + def end_point + meta_data = "" + channel_keys = [] + @channels.each do |c| + c.to_sym + if Categories.CHANNELS.include?(c) + channel_keys << Categories.CHANNELS[c] + end + end + meta_data = channel_keys.collect { |channel| "meta:channel=#{Search.double_encode_channel(channel)}" }.join("+OR+") + puts meta_data + + + # meta_data = self.channels.join("+OR+") + + meta_data += "+AND+" unless meta_data == "" + if @start_date.class == Date + @start_date = URI.escape(@start_date.strftime("%m/%d/%Y")).gsub(/\//,"%2F") + end + if @end_date.class == Date + @end_date = URI.escape(@end_date.strftime("%m/%d/%Y")).gsub(/\//,"%2F") + end + meta_data += "meta:startDate:daterange:#{@start_date}..#{@end_date}" + url = "#{SEARCH_URL}/search?api_key=#{@api_key}&num=#{@num_results}&page=#{@page}&l=#{@location}&f=#{@facet}&v=#{@view}&r=#{@radius}&s=#{@sort}&k=#{@keywords.join("+")}&m=#{meta_data}" + end + + def search + searchurl = URI.parse(end_point) + req = Net::HTTP::Get.new(searchurl.path) + http = Net::HTTP.new(searchurl.host, searchurl.port) + http.read_timeout = DEFAULT_TIMEOUT + + puts "#{searchurl.path}?#{searchurl.query}" + + res = http.start { |http| + http.get("#{searchurl.path}?#{searchurl.query}") + } + + if (200..307).include?(res.code.to_i) + parsed_json = JSON.parse(res.body) + @endIndex = parsed_json["endIndex"] + @pageSize = parsed_json["pageSize"] + @searchTime = parsed_json["searchTime"] + @numberOfResults = parsed_json["numberOfResults"] + @results = parsed_json['_results'].collect { |a| Activity.new(a) } + else + raise RuntimeError, "Active Search responded with a #{res.code} for your query." + end + end + + # examples + # + # Search.new({:location => "San Diego"}) + # + # Keywords can be set like this + # Search.new({:keywords => "Dog,Cat,Cow"}) + # Search.new({:keywords => %w(Dog Cat Cow)}) + # Search.new({:keywords => ["Dog","Cat","Cow"]}) + # + # http://developer.active.com/docs/Activecom_Search_API_Reference + # returns an array of results and query info + def self.search(data=nil) + search = Search.new(data) + search.search + return search + end + + def self.construct_url(arg_options={}) + return arg_options[:url] if arg_options.keys.index(:url) #todo use has_key? #a search url was specified - bypass parsing the options (trending) + # self.merge!(arg_options) + + # options[:location] = CGI.escape(options[:location]) if options[:location] + + # if options[:keywords].class == String + # options[:keywords] = options[:keywords].split(",") + # options[:keywords].each { |k| k.strip! } + # end + + # if options[:channels] != nil + # channel_keys = [] + # options[:channels].each do |c| + # c.to_sym + # if self.CHANNELS.include?(c) + # channel_keys << self.CHANNELS[c] + # end + # end + # channels_a = channel_keys.collect { |channel| "meta:channel=#{Search.double_encode_channel(channel)}" } + # end + + meta_data = "" + meta_data = channels_a.join("+OR+") if channels_a + + meta_data += "+AND+" unless meta_data == "" + if options[:start_date].class == Date + options[:start_date] = URI.escape(options[:start_date].strftime("%m/%d/%Y")).gsub(/\//,"%2F") + end + + if options[:end_date].class == Date + options[:end_date] = URI.escape(options[:end_date].strftime("%m/%d/%Y")).gsub(/\//,"%2F") + end + meta_data += "meta:startDate:daterange:#{options[:start_date]}..#{options[:end_date]}" + + url = "#{SEARCH_URL}/search?api_key=#{options[:api_key]}&num=#{options[:num_results]}&page=#{options[:page]}&l=#{options[:location]}&f=#{options[:facet]}&v=#{options[:view]}&r=#{options[:radius]}&s=#{options[:sort]}&k=#{options[:keywords].join("+")}&m=#{meta_data}" + puts url + url + self.end_point = url + end + + private + def self.double_encode_channel str + str = URI.escape(str, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")) + str = URI.escape(str, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")) + str.gsub!(/\-/,"%252D") + str + end + + end + + class Categories def self.CHANNELS { :active_lifestyle => '', :fitness => 'Fitness', :body_building => 'Fitness\Body Building', @@ -158,106 +320,9 @@ :volleyball => 'Volleyball', :walking => 'Walking', :wrestling => 'Wrestling' } end - - - # http://developer.active.com/docs/Activecom_Search_API_Reference - # - def self.search(data=nil) - searchurl = URI.parse(construct_url(data)) - req = Net::HTTP::Get.new(searchurl.path) - http = Net::HTTP.new(searchurl.host, searchurl.port) - http.read_timeout = DEFAULT_TIMEOUT - - res = http.start { |http| - http.get("#{searchurl.path}?#{searchurl.query}") - } - - # if res.code == '200' or res.code == '307' - if (200..307).include?(res.code.to_i) - parsed_json = JSON.parse(res.body) - return parsed_json["numberOfResults"] if data.has_key?(:show_number_of_results) - query_addl_info= {:endIndex=>parsed_json["endIndex"], :pageSize=>parsed_json["pageSize"], :searchTime=>parsed_json["searchTime"], :numberOfResults=>parsed_json["numberOfResults"]} - parsed_json['_results'].collect { |a| Activity.new(a.merge query_addl_info) } - else - raise RuntimeError, "Active Search responded with a #{res.code} for your query." - end - end - - def self.construct_url(arg_options={}) - options = { - :api_key => "", - :view => "json", - :facet => Facet.ACTIVITIES, - :sort => Sort.DATE_ASC, - :radius => "50", - :meta => "", - :num_results => "10", - :page => "1", - :location => "", - :search => "", - :keywords => [], - :channels => nil, - :start_date => "today", - :end_date => "+" - } - options.merge!(arg_options) - - return arg_options[:url] if arg_options.keys.index(:url) #a search url was specified - bypass parsing the options (trending) - - options[:location] = CGI.escape(options[:location]) if options[:location] - - if options[:keywords].class == String - options[:keywords] = options[:keywords].split(",") - options[:keywords].each { |k| k.strip! } - end - if options[:channels] != nil - - channel_keys = [] - options[:channels].each do |c| - c.to_sym - if self.CHANNELS.include?(c) - channel_keys << self.CHANNELS[c] - end - end - - channels_a = channel_keys.collect { |channel| "meta:channel=#{Search.double_encode_channel(channel)}" } - end - - meta_data = "" - meta_data = channels_a.join("+OR+") if channels_a - - meta_data += "+AND+" unless meta_data == "" - if options[:start_date].class == Date - options[:start_date] = URI.escape(options[:start_date].strftime("%m/%d/%Y")).gsub(/\//,"%2F") - end - - if options[:end_date].class == Date - options[:end_date] = URI.escape(options[:end_date].strftime("%m/%d/%Y")).gsub(/\//,"%2F") - end - meta_data += "meta:startDate:daterange:#{options[:start_date]}..#{options[:end_date]}" - - # if @asset_type_id!=nil - # @meta = @meta + "+AND+" if @meta!="" - # @meta = @meta + "inmeta:assetTypeId=#{@asset_type_id}" - # end - # - url = "#{SEARCH_URL}/search?api_key=#{options[:api_key]}&num=#{options[:num_results]}&page=#{options[:page]}&l=#{options[:location]}&f=#{options[:facet]}&v=#{options[:view]}&r=#{options[:radius]}&s=#{options[:sort]}&k=#{options[:keywords].join("+")}&m=#{meta_data}" - puts "//////" - puts url - puts "//////" - url - end - - private - def self.double_encode_channel str - str = URI.escape(str, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")) - str = URI.escape(str, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")) - str.gsub!(/\-/,"%252D") - str - end - end + end end \ No newline at end of file