How to set up kaminari correctly - ruby-on-rails

I'm using kaminari gem for pagination. The problem is that I need to paginate on the first page after 4 elements, and on the all other pages after 25 elements. It it possible to configure kaminari to solve my problem?
Here is a usage:
.pagination
.pagination__back
- if params[:page] && params[:page].to_i > 1
= link_to "Previous news", news_items_path(page: params[:page].to_i - 1)
- else
= ""
.pagination__forward
- if params[:page]
= link_to "Next news", news_items_path(page: params[:page].to_i + 1)
- else
= link_to "Next news", news_items_path(page: 2)

First of all you can leave out all the code related to forward/previous pages. Kaminari solves this with its helper already.
For that matter, inside your view, use the following code:
= paginate #your_resource
This will render several ?page=N pagination links surrounded by an HTML5 tag.
(Source)
To have a paginated resource, you want to add the following code to your controller:
#your_resource = YourResource.order(:foobar).page(params[:page])
# params[:page] will get added to each "paginated" request by Kaminari
# if you use its previously mentioned helper method.
Now you want a dynamic limit. For that matter I suggest adding something like this:
def index
#your_resource = YourResource.order(:foobar).page(params[:page]).per(dynamic_limit(params[:page]))
end
private
def dynamic_limit(current_page = 1)
if current_page == 1
return 4
else
return 25
end
end
This way you will check for the current page, and if it's the first page it'll limit the results to 4. Otherwise, 25.

Related

How can I send paginated requests to third party API in 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

How to do SEO link tag for two/multiple pagination in single page?

I wrote an application in rails 4. In that app, I have two pagination in single page 'x (page)'. Params like groups and page in the url.
Url looks like:
https://example.com/x?page=2&group=4
Initial page:
https://example.com/x
If pagination page params, then
https://example.com/x?page=2
If paginating groups params, then
https://example.com/x?group=2
If paginating both,then
https://example.com/x?page=2&group=2
and so on.
I am using Kaminari gem to do pagination. In that gem I used rel_next_prev_link_tags helper to show link tag for prev/next.
How to show link tags for multiple pagination?
I created an custom helper to process the URL and based on params create the categorized link tags. ex: In view,
pagination_link_tags(#pages,'page') for pages pagination
pagination_link_tags(#groups,'group') for groups pagination
def pagination_link_tags(collection,pagination_params)
output = []
link = '<link rel="%s" href="%s"/>'
url = request.fullpath
uri = Addressable::URI.parse(url)
parameters = uri.query_values
# Update the params based on params name and create a link for SEO
if parameters.nil?
if collection.next_page
parameters = {}
parameters["#{pagination_params}"] = "#{collection.next_page}"
uri.query_values = parameters
output << link % ["next", uri.to_s]
end
else
if collection.previous_page
parameters["#{pagination_params}"] = "#{collection.previous_page}"
uri.query_values = parameters
output << link % ["prev", uri.to_s]
end
if collection.next_page
parameters["#{pagination_params}"] = "#{collection.next_page}"
uri.query_values = parameters
output << link % ["next", uri.to_s]
end
end
output.join("\n").html_safe
end
You can't show search engines two-dimensional pagination. In your case it looks more like grouping/categorizing + pagination.
Like:
Group 1 pages:
https://example.com/x
https://example.com/x?page=2
https://example.com/x?page=3
Group 2 pages:
https://example.com/x?group=2
https://example.com/x?page=2&group=2
https://example.com/x?page=3&group=2
Etc.

show all results on one page (gem kaminari)

I have data and they be cut on some pages (10 results per page).
code in controller:
#messages = Message.order('id DESC').page params[:page]
How I can show all results on one page if I want? It similar as 'see all' on page navigate.
You can put a very high limit in the per_page option if you still want the paginate helpers to work in your view.
#messages = Message.order('id DESC').page params[:page]
if params[:all]
#messages = #messages.per_page(Message.count) # you can also hardcod' it
end

how to redirect to the "operating" page in will_paginate

I have a message box using will_paginate.
I have 6 messages showing in 3 pages,
when i delete an item in page_3, it redirect_to page_1, how can i still be in page_3?!
2 ways to solve the issue:
"redirect_to :back"
save params[:page] and redirect to the page once item is deleted
You can use method total_pages on instance variable which you are using for pagination.
example :
#user = User.find(params[:id])
#comments = #user.comments.paginate(:page => 1, :per_page => 20)
#comments.total_pages
#comment.total_pages will return you the last page no. which you can use for your redirection.

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.

Resources