ShopifyAPI: Product find since_id strangeness - ruby-on-rails

there is something strange going on with the Shopify API, I cannot understand what I am doing wrong.
I'd like to get from Shopify a list of all the products so I use the following code:
def get_all_products_from_shopify
limit = 250
all_products = Array.new
self.connect_to_store
products = ShopifyAPI::Product.find(:all, :params => {:limit => limit})
all_products = all_products.concat products
puts products.length
while products.length == limit do
since_id = products.last.id
products = ShopifyAPI::Product.find(:all, :params => {:limit => limit, :since_id => since_id})
all_products = all_products.concat products
end
ShopifyAPI::Base.site = nil
return all_products
end
The issue is that I have 251 products on Shopify but with this method I retrieve an array of products that has a size of 277 elements.
Why?
Also if I do:
products = ShopifyAPI::Product.count
> 251
products = ShopifyAPI::Product.find(:all, :params => {:limit => limit})
products.count
>250
since_id = products.last.id
ShopifyAPI::Product.count(since_id: since_id)
>26
Can anybody tell me what am I doing wrong?
Thanks,
Augusto

By default products are returned in ascending order by title in the product list API. Instead of omitting the :since_id param for the first page of results, use :since_id => 0.

Related

How to custom sort based on user interests?

In the existing product controller, we are sorting products based on price.
def index
#products = Product.all.order(price: :asc)
#products = #products.paginate(:page => params[:page], :per_page => 20)
end
Now, I would like to change the sorting so that we will user interests. The over all sorting policy will be like this:
items belonging to user interested categories will be listed at top. Remaining items will be listed afterwards.
Within user interested grouping, products shall be ordered based on price. (similar approach for the non interested grouping).
Users Table
id name interested_categories
1 Alice [ 10, 11 ]
2 Bruce [ 11 ]
3 Carol [ 10, 12 ]
Categories Table
id category_name
10 School
11 Kitchen
12 Camping
Products Table
id product_name price category_id
1 pencil 2 10
you could try this
def index
filtered_products = Product.where(category_id: current_user.interested_categories)
all_products = Product.where.not(category_id: current_user.interested_categories).order(price: :asc)
#final_products = (filtered_products+all_products).paginate(:page => params[:page], :per_page => 20)
end
then your views take the #final_products or just change the variable into #products
filtered_products = Product.where(category_id: current_user.interested_categories).to_a.sort_by { |product| [product.category, product.price] }
remaining_products = Product.where.not(category_id: current_user.interested_categories).to_a.sort_by { |product| product.price }
#products = filtered_products + remaining_products.paginate
Converting to Array allows you to use sort_by to sort by two criteria.

Ruby on Rails get unique country from Query results

Following were my query to get list of products:
#listed_products = #products.where(:step => 5, :status => 1)
.includes(:product_attachments)
.includes(:product_reviews)
.order("created_at desc")
The result return products which also consist many similar country eg:
name:prod1
city:city1
country:A
name:prod2
city:city3
country:A
name:prod3
city:city5
country:B
How can I filter out just unique country A,B from the result query? I just need country list to build a drop down list for user to sort product based on country. Thanks!!
You can try this -
#listed_products = #products.where(:step => 5, :status => 1)
.includes(:product_attachments)
.includes(:product_reviews)
.order("products.created_at desc")
result = #listed_products.pluck(:country).uniq
Try the below code:
#listed_products = #products.where(:step => 5, :status => 1)
.includes(:product_attachments)
.includes(:product_reviews)
.order("created_at desc").uniq.pluck(:country)

rails activerecord swap data

I need to make 1 product in the top of the list. I tryed:
#allProd = Product.where(service_id:params[:id], product_category_id:descenId).order(rating: :desc).paginate(:page => params[:page], :per_page => 8)
tmp = #allProd[0]
indx = #allProd.find_index(Product.find(prodId))
#allProd[0] = #allProd[indx]
#allProd[indx] = tmp
But array of datas are not changed. What is the best way to do this?
UPD:
Final solution was
#allProd = Product.where(service_id:params[:id], product_category_id:descenId).order(rating: :desc).paginate(:page => params[:page], :per_page => 8).to_a
#allProd.delete(Product.find(prodId))
#allProd = #allProd.unshift(Product.find(prodId))
But keep in mind that you will have problems with number of paginated products if shifted product is in not first page. But for me, it is ok)
I am not 100% sure that this is what you are trying to achieve, but can try
#allProd = Product.where(service_id:params[:id], product_category_id:descenId).order(rating: :desc).paginate(:page => params[:page], :per_page => 8).to_a.unshift(Product.find(prodId))
I assume that on each page Product with id prodId will be the first.
Sorry but I am also interested, why do you need to swap elements? If you only make 1 product in the top of the list then use "unshift" function.
#allProd=[[]]
#allProd = Product.where(service_id:params[:id], product_category_id:descenId).order(rating: :desc)
#allProd=#allProd.unshift(name_of_product_obj_you_want_to_add_at_top)
And then apply pagination to "#allProd" array.

Getting an average count based on parameters from both the parent and child model

If a User has_many Items. And items can be published by setting the :published attribute in items to true.
How do I get the average number of published items, per user that created an item?
I have a scope for items called published, so you can get all published items by writing:
#items = Item.published
#items = #user.items.published
One way is:
avg = Item.published.count.to_f / User.count
EDIT:
Try this:
#published_items = User.joins(:items).where('items.published = ?', true)
avg = #published_items.count.to_f / #published_items.all(:select => 'distinct users.*').count
Or:
avg = Item.published.count.to_f / User.joins(:items).where('items.published = ?', true).all(:select => 'distinct users.*').count

How do I search trough query results, to prevent making to many requests

I have the below set of queries, but I'm sure this isn't DRY. However, I can't find out how to filter trough the deals var instead of querying again for each var. Is it possible?
deals = Deal.all
won = Deal.find( :all, :conditions => ["status = 'won'"] ).count
pending = Deal.find( :all, :conditions => ["status = 'pending'"] ).count
lost = Deal.find( :all, :conditions => ["status = 'lost'"] ).count
Use GROUP BY SQL clause:
Hash[Deal.all(:select => 'status, count(*) as count', :group => 'status').map{|e|
[e.status, e.count]
}]
Edit: I forgot that you already have all the records loaded. In that case, you can get counts per status this way:
Hash[deals.group_by(&:status).map{|k,v| [k,v.count]}]
You can use following:-
Deal.find(:all, :select => 'status, count(id) as deal_count', :group => 'status')
You can use Array#select:
deals = Deal.all
won = deals.select { |deal| deal.status == 'won' }.length
# similar for pending and lost
I think you can use Ruby's inject function for this:
won = deals.inject(0) {|total, deal| deal.status == 'won' ? total + 1 : total }
if your Deal objects are ActiveRecord objects (which is typically the case for models), you can launch the count on the data base:
won = Deal.count_by_sql("select count(*) from deals where status = 'won'")
Another way to do it would be to write the sql query that would do the all the count for you, and group them by status:
count_by_status = Deal.find_by_sql("select status,count(*) from deals group by status;")
Then you can use the result (which will be an array of hashes I think).

Resources