Is there a way to do cursor pagination in searchkick? - ruby-on-rails

I'm using kaminari with searchkick to paginate my data, getting my search results by calling the method like so:
Product.search(#query, where: conditions[:where], order: conditions[:order], page: #page, per_page: 20)
My data is updated frequently, with more products being added so if a client is on page 1 and navigates to page 2, they might see products that they already saw in the previous page. Is there a way around this? I'm not very sure how to handle this using searchkick and would appreciate any pointers.

Related

rails pagy multiple tables on one page

I have two different tables on one page and I want to use pagy on each of them.
For sorting/searching I changed names of each pagy object so I did it like
#pagy_inv, #invoices = pagy #invoices.reorder(sort_column_show_city_invoices => sort_direction_show_city_invoices), items: params.fetch(:count, 10)
and
#pagy_ord, #orders = pagy #orders.reorder(sort_column_show_city_orders => sort_direction_show_city_orders), items: params.fetch(:count, 10)
which works fine for sorting and searching, but when I try to change page, it sends page parameter and tries to change page for every table and therefore if one table has like 5 pages and another 10 and I try to move to page 10 it fails because one of the table cannot move to not existing table.
I was thinking to change page param (for example page_inv and page_ord) but how to do that? Or is there some easy way how to change page only for table from selected pagy object?
As you already understood, pagy use a default :page_param (which is :page): if you use more than one instance in the same page you should differentiate the :page_param of different instances or they will use all the same.
You can pass that in the pagy method (as you did with :items).

will_paginate mass operations with specific page don't work

Rails 4.2.5 and will_paginate 3.1.0.
I was stuck for some time being unable to do mass operations (like update_all) with will_paginate, and while investigating I've found some strange behavior. Could anyone please explain the reason behind it?
Let's say I have 22 users in the database and per_page = 10:
User.all.page(3) will return correct users (user 21 and user 22),
however:
User.all.page(3).count # => 22
while
User.all.offset(2 * User.per_page).limit(User.per_page).count # => 2
The specific problem I was dealing with is that if I do something like this:
User.all.page(3).update_all(flagged: true)
I get the first page updated (users 1-10) and not the third one (users 21-22).
Is there a way to use will_paginate page method inside a controller to manipulate records within the specific page only?
Update:
The funny thing is that even with .offset().limit() mass update still won't work and I get the same results: the first page is updated instead of the last one (users 1-10, and not 21-22).
So while
User.all.offset(2 * User.per_page).limit(User.per_page).count # => 2
the User.all.offset(2 * User.per_page).limit(User.per_page).update_all(flagged: true) still updates the first 10 users and not the last 2.
The only way I came up with so far is to do User.all.page(3).each { |user| user.update(flagged: true) } which works fine but seems to be terribly ineffective.
Try to add .per_page(10) to your active record query

will_paginate on limite records

I have a problem to paginate the record that I request from other web service to get data. When i make a request i get some data(not all because if i get all it will be too big) and the total number of records. will_paginate seem can only display the first page and from the second page it show nothing.
page = params[:page]? params[:page]:1
#fields = ConflictCase.get_fields
sites = ConflictCase.get_paging_sites_from_service(10, (page.to_i - 1)) #this will request data from other webservice that I limit only 10 records
#conflict_cases = ConflictCase.transform(sites["sites"], #fields)
#conflict_cases = #conflict_cases.paginate(:page => page, :per_page => 10, :total_entries => sites["total"].to_i)
The problem is that i always get only 10 records so it can display on the first page but from the second page it show nothing. I though because will paginate will work on it own to ignore the first 10 records when we move to second page or more.
Have anyone can suggest any idea?
Thank for your help
This is a perfect scenario to use the ruby debugger, or spit out to the logger the values during each iteration of your objects.
Firstly I would assume will_paginate isn't the issue, so I would debug to look at the #conflict_cases object and what is being passed into the paginate() function, and the values each time for page and sites['total'].

How can I set default page to the last page when using pagination?

Assuming there are 115 communities.
Then it show 10 communities per page with pagination.
When I'm going to example.com/communities, it shows 10 oldest records.
However, I want it to link to example.com/communities?page=12 as default.
It should be linked to the last page of communities.
Is it possible?
Now my link is just like this
<%= link_to "Communities", communities_path %>
This is possible but you have to add some logic
communities = Community.page(params[:page])
communities.total_pages # 12
communities_path(page: communities.total_pages)
or you can just reverse the ordering of your query.
Another way of thinking about it. Change your order by so it shows the newest.
So on your arel query, do something like this:
Blog.all.order("id desc")
I left the pagination call out as i do not know what pagination library you are using :).

pagination and memcached in rails

What's the best way to cache a paginated result set with rails and memcached?
For example, posts controller:
def index
#posts = Rails.cache.fetch('all_posts') do
Post.paginate(:conditions => ['xx = ?', yy], :include => [:author], :page => params[:page], :order => 'created_at DESC')
end
end
This obviously doesn't work when the params[:page] changes. I can change the key to "all_posts_#{params[:page]}_#{params[:order]_#{last_record.created_at.to_i}", but then there could be several possible orders (recent, popular, most voted etc) and there will be a combination of pages and orders ... lots of keys this way.
Problem #2 - It seems that when I implement this solution, the caches get written correctly and the page loads fine during the first call to a paginated action. When I click back on the same page i.e. page1, with recent order, it seems the browser does not even make a call to the server. I don't see any controller action being called in the production log.
I am using passenger, REE, memcached, and rails 2.3.5. Firebug shows no requests being made....
Is there a simples/more graceful way of handling this?
When it comes to caching there is no easy solution. You might cache every variant of the result, and thats ok if you implement auto-expiration of entries. You can't just use all_posts, because this way you will have to expire dozens of keys if posts will get changed.
Every AR model instance has the .cache_key based on updated_at method, which is prefered way, so use this instead of last record. Also don't base your key on last record, because if some post in the middle will get deleted your key wont change. You can use logic like this instead.
class ActiveRecord::Base
def self.newest
order("updated_at DESC").first
end
def self.cache_key
newest.nil? ? "0:0" : "#{newest.cache_key}:#{count}"
end
end
Now you can use Post.cache_key, which will get changed if any post will get changed/deleted or created.
In general I would just cache Post.all and then paginate on this object. You really need to do some profiling to find bottle necks in your application.
Besides, if you want to cache every variant, then do fragment/page caching instead.
If up to you how and where to cache. No one-way here.
As for the second part of the question, there is way to few hints for me to figure an answer. Check if the browser is making a call at all LiveHTTPHeaders, tcpdump, etc.

Resources