Skip to content

Instantly share code, notes, and snippets.

@nikosd
Created January 18, 2009 11:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nikosd/48624 to your computer and use it in GitHub Desktop.
Save nikosd/48624 to your computer and use it in GitHub Desktop.
class ItemFetcherWorker < BackgrounDRb::MetaWorker
set_worker_name :item_fetcher_worker
def create(args = nil)
end
def set_search(search)
@search = search
end
def fetch_query_and_items
times_tried = 0
begin
times_tried = times_tried + 1
@search.do!
rescue
times_tried < 4 ? retry : raise
end
fetch_items
end
def fetch_items
times_tried = 0
begin
times_tried = times_tried + 1
@search.items
rescue
times_tried < 4 ? retry : raise
end
end
def fetch_next_page_of_items(params = {})
# query_options = params[:query_options]
total_pages = params[:total_pages].to_i || 1
current_page = params[:current_page].to_i || 1
depth = params[:depth] || 2
if current_page < total_pages
new_params = @search.request.call_params.merge({:page_number => (current_page.to_i + 1).to_s})
logger.info("---------------------------------\nSearch begun for:\n #{@search.request.call_params}\nwith new parameters:\n #{new_params}")
@search = Search.new(new_params)
@search.do!
@search.items
logger.info("Search finished!\n---------------------------------\n")
fetch_next_page_of_items(:total_pages => total_pages, :current_page => current_page, :depth => depth-1) if depth > 0
end
rescue
logger.error("Search finished but something broke:\n #{$!}\n---------------------------------\n")
end
end
class Search
# Example: Search.new(:query_keywords => 'canon (450d, xti)', :"price_min.Value" => 400, :"price_max.Value" => 1100, :max_entries => 5)
#
# Also perfmorms the EbayShopping::Request.
#
# Raises hell of exceptions some of which are:
# SocketError (getaddrinfo: nodename nor servname provided, or not known)
# EbayShopping::TimeoutError
attr_reader :request
def initialize(params)
params_default = {
:max_entries => '5',
:include_selector =>'Details,SellerInfo',
:item_type => 'AllItemTypes', # includes "Store Inventory format" in addiction to auction items
:items_available_to => 'GR',
:item_sort => 'EndTime', # Maybe by best-match?
:payment_method => 'PayPal'
#:site_id => '3' # Ebay.co.uk
}
@request = EbayShopping::Request.new :find_items_advanced, params_default.merge(params)
@error = nil
end
def cached?
if @request.has_cached_response?
self.do!
true
end
end
def do!
@response = @request.response
end
# Returns an array of Items with the result set from the request/response.
def items(options = {})
return nil if total_items == 0
options = {:caclulate_shipping => true, :shipping_for_country_code => 'GR', :get_seller_details => false}.merge(options)
@items = @response.items.map{ |item| EbayItem.find_or_create_from_ebay_response(item, options) }
end
def total_items
@total_items ||= @response.total_items
end
def items_cached?
return true unless @response.items # Return true if items is empty
return EbayItem.count(:conditions => {:item_id => @response.items.map { |item| item.item_id } }) == @response.items.size
end
end
class SearchController < ApplicationController
layout 'default'
# GET /
# GET /search
# GET /search/index
def index; @pagetitle = 'simpleBay: Τί ψάχνεις σήμερα;'; end
# GET /search?q=''&max_price=''&...
# GET /search/search?q=''&max_price=''&...
#
# Required parameters: q
# Optional parameters: page, min_price, max_price, max_entries
def search
@repeat_request = false
if params[:q].nil? or (@q = params[:q]).empty?
render :text => 'Καλό θα ήταν να εισάγετε κάτι για αναζήτηση :)' and return
end
@pagetitle = "simpleBay: Αναζήτση για #{@q}"
parse_ebay_parameters
search = Search.new(@ebay_req_params)
fetcher = MiddleMan.worker(:item_fetcher_worker)
fetcher.set_search(:arg => search)
if search.cached?
@total_results = search.total_items
if search.items_cached?
@items = search.items
@current_page, @total_pages = (@ebay_req_params[:page_number] || 1).to_i, (@total_results / @ebay_req_params[:max_entries].to_f).ceil
if @total_results > (@current_page * @ebay_req_params[:max_entries].to_i)
fetcher.async_fetch_next_page_of_items(:arg => {:current_page => @current_page, :total_pages => @total_pages})
end
else # if items are NOT cached.
@repeat_request = true
fetcher.async_fetch_items unless request.xhr?
end
else # if search is NOT cached.
@repeat_request = true
fetcher.async_fetch_query_and_items unless request.xhr?
end
# Setup params for periodically_call_remote in search view template if request is to be repeated.
@ajax_url_params = {:action => :search,
:q => @q,
:page => @ebay_req_params[:page_number],
:min_price => @min_price,
:max_price => @max_price,
:max_entries => @max_entries } if @repeat_request
rescue EbayShopping::TimeoutError
render :text => 'Ebay timeout error, please try again later'
end
protected
def parse_ebay_parameters
@ebay_req_params = { :query_keywords => @q }
@ebay_req_params[:page_number] = params[:page] || '1'
if @min_price = params[:min_price] and !@min_price.empty?
@ebay_req_params[:"price_min.Value"] = EbayShopping::Money.euros_to_dollars(@min_price)
end
if @max_price = params[:max_price] and !@max_price.empty?
@ebay_req_params[:"price_max.Value"] = EbayShopping::Money.euros_to_dollars(@max_price)
end
@ebay_req_params[:max_entries] = @max_entries = params[:max_entries] ? params[:max_entries] : 10
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment