How can I send paginated requests to third party API in rails - ruby-on-rails

Im building a web application in rails to fetch records from a third party API. This third party API accepts page parameter. For eg: GET http://thirdpartyapi.com/records?page=2
How can I build my html in paginated format, so that when user clicks on number 2, it should send page=2 and when user clicks on number 4, it should send page=4 in the requests. Is there any gem for that?
class DemoController < ApplicationController
def index
response = HTTP.get('http://thirdparty.com/records', {query: {page: params[:page]}}) # it will return 30 items by default
#items = response['items'].paginate(page: params[:page], per_page: 10)
end
end
This is my views
<%= will_paginate %>

If you want to do this manually it's more work than just using the will_paginate gem
First you would need to get a count of records so that you know how many pages (aka how many links at the bottom you will have for pages)
#num_of_records = Object.count / per_page
Then you will need to handle that through JS depending on the number of links you want to display.
Once a user clicks on yourlink.com/?page=2 it should load with the correct data, or if you choose to you can remove elements from the div/table and insert new ones by returning them if you do an AJAX call.
Your controller would look something like this:
def index
page = params[:page] || 1
per_page = 10
#num_of_records = Object.count / per_page
objects_to_append = Object.paginate(:page => page, :per_page => perPage)
render json: { success: true, objects_to_append: objects_to_append }
end

I highly recommend to use kaminari instead. they have a way to do this easily.
https://github.com/kaminari/kaminari#paginating-a-generic-array-object

Related

Can I Check if a Controller is Being Called from an AMP page in Rails?

I'm starting to implement AMP pages in my Rails 5.2 app. On desktop, I'm using the Will Paginate gem.
However, with AMP I'm using the framework's infinite scroll JS, and I don't want to paginate the results.
So in the controller action, I want to determine if the user is viewing an AMP page (the URL ends with .amp) to determine what I have for this line (include paginate or exclude):
#products = #products.order('price DESC, RANDOM()').paginate(page: params[:page], per_page: 24)
How do I do this?
The simple solution is just test request.format. So you could write
if request.format == :amp
# do not paginate
else
# all other formats we paginate
end
But inside a controller, we can also use an explicit respond_to block:
def index
respond_to do |format|
format.amp do
#products = #products.order('price DESC, RANDOM()')
end
format.html do
#products = #products.order('price DESC, RANDOM()').paginate(page: params[:page], per_page: 24)
end
end
end
This will explicitly specify all the formats the controller method accepts and responds to.
As you probably already do, but you will have to provide a view for index.amp and a index.html.
To be clear: this will also block all non-specified formats! E.g. retrieving a index.json will get a 405 Not allowed.

Limit the Elasticsearch results count in Rails

I'm running Rails with Elasticsearch using the elasticsearch-rails and will_paginate gems and things are working great.
The only problem I'm having is that my records count has grown over 10.000 which gives the error "Result window is too large, from + size must be less than or equal to: [10000] but was [10200]" when someone clicks on the last page of the pagination links.
Now I don't want to mess with index.max_result_window because my dataset is going be much much larger and I really don't need visitors to be able to view every page and record anyway.
So basically I just want to set a limit of 10.000 on my results but I'm having no luck getting that working.
This is the query I have in my controller action:
#response = Price.search(params)
#response = #response.paginate(page: params[:page], per_page: 24)
#prices = #response.records.includes(shop: :pictures)
#prices_count = #response.total_entries
#prices = #prices.decorate
#results = #response.results
And I feed the #response to will_paginate using
will_paginate(#response)
I've tried using .limit(10000) in various places and giving a total_entries value to will_paginate but nothing seems to work.
Do you guys have any ideas?
Thanks!
I had the same Issue, in my case I'm using kaminari but should work the same with will_paginate:
= paginate #keyword_search_results
With 25 results per page after 400 page it throws the index.max_result_window error, so I just add the :total_pages option to paginate
= paginate #keyword_search_results, {:total_pages => 400}
Would be a good idea to calculate that value dynamically based on your needs.
use per_page option
#response = Price.search(params, per_page: 24)

will_paginate usage with web call

my index action calls out to the web
response = HTTParty.get('http://www.ask.com/open')
I added pagination to the index, because there were too many results
#asks = ask.paginate(:page => params[:page], :per_page => 5)
and the corresponding call to will_paginate in my view
The problem I have is when the user clicks to move to the next page, it results in the service all being made to the server. I want to just have it fetch the results from model if it is a pagination call, but call the service if the index is being called directly.

Google custom search API with pagination

I have this method that puts the links of the 10 results from the Google custom search API into an array:
require 'json'
require 'open-uri'
def create
search = params[:search][:search]
base_url = "https://www.googleapis.com/customsearch/v1?"
stream = open("#{base_url}key=XXXXXXXXXXXXX&cx=XXXXXXXXXX&q=#{search}&start=#{i}&alt=json")
raise 'web service error' if (stream.status.first != '200')
result = JSON.parse(stream.read)
#new = []
result['items'].each do |r|
#new << r['link']
end
end
and my view:
<% #new.each do |link| %>
<p><%= link %></p>
<% end %>
I'm having trouble figuring out how to add pagination with this so that on the second page would return the next 10 results. I'm using the Kaminari gem for pagination.
I want for when a user clicks a link to another page, I fetch the next 10 results from Google's API. You can do this with the API's start parameter that specifies the first result to start with, which I pass as i. I was thinking of doing something like this:
i = (params[:page] - 1) * 10 + 1
where params[:page] is the current page number, but for some reason it is undefined. Also I'm unsure about how to setup pagination for an array that is not an AR object, and what would go in my view. I'd appreciate any help, and feel free to use any pagination gem you know.
How are you setting params[page]? It needs to be passed in with the other parameters in your request in some way.
Perhaps you need something like this in your controller:
#page = params[:page] || 1
i = (#page - 1) * PER_PAGE + 1
stream = open("#{base_url}key=XXXXXXXXXXXXX&cx=XXXXXXXXXX&q=#{search}&start=#{i}&alt=json")
raise 'web service error' if (stream.status.first != '200')
result = JSON.parse(stream.read)
#new = result['items'].map{|r| r['link']}
In your view you need to make sure that you are passing the page via the query parameter in the link to fetch the next set of results. Most likely that you would want to return #page + 1.
Handling pagination with non ActiveRecord objects depends on your pagination library. You might want to check out how will_paginate handles this.

Pagination and table sorting in Rails

I am using will_paginate and sort helper for pagination and sorting resp..
But im facing one problem while sorting that when im on page 2 or 3 or any other page than first page.
It redirects to the first page and sorts the first page only.
please help me how to sort all the records and go back to page where I was.
What's the reason you need to go back to the page (2 or 3)? Records will change position and probabily page so you will not find them at the same place.
so why you don't change only the :order value (ex. from 'firstname DESC' to 'lastname DESC) when you call the action again?
# people_controller.rb
def index
#people = People.search(params[:my_order], params[:page])
end
# models/people.rb
def self.search(my_order, page)
paginate :per_page => 10, :page => page,
:conditions => ['job like ?', "Driver"],
:order => "%#{my_order}%"
end
I have more powerful solution for this: https://github.com/mynameisrufus/sorted

Resources