will_paginate on limite records - ruby-on-rails

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'].

Related

Is there a way to do cursor pagination in searchkick?

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.

Conditionally insert date separator to array of chat messages

I'm working on a Chat feature, similar to Slack, where the messages are grouped by date. I'm using the groupdate gem to put all of the messages together in a hash, and then print them out in the browser where messages are grouped by the date they were sent on:
#messages = #chatroom.messages.group_by_day { |message| message.created_at }
- #messages.each do |day, messages|
%li.date_divider
= "#{day.strftime("%B %d")}"
%ul
- messages.each do |message|
%li= message.content
For performance, it's crazy to load months worth of messages all at once and I'm trying to think how I can approach this by paginating the messages and using some sort of infinite autoscroll. I can get this working fine using #pagy, #messages = pagy(#chatroom.messages) but all of it goes to hell when I use the group_by_day and returned in a hash. I was curious if you anyone could shed some input on how to approach this where I can still benefit from the user-experience by grouping messages by date, but also benefit from the performance in the case outlined above.
Alternative to using group_by_day, one suggestion is to paginate an array of messages ordered by date and conditionally add the extra date display in the loop to display when the next item have a new date compared to the previous one, but I'm unsure how to do this off the top of my head.
You're not far of an actual working version, when you do:
# controller
#pagy, #messages = pagy(#chatroom.messages)
The messages are stored in #messages. When you call #chatroom.messages.group_by_day you call group_by_day upon all messages belonging to the chatroom. Instead use #messages.group_by_day which holds the messages that are retuned by pagy.
-# view
- #messages = #messages.group_by_day { |message| message.created_at }
- #messages.each do |day, messages|
-# ...
For infinite scroll there you might want to use a library. The basic idea is to fetch messages from the server when the user scrolls close to the top or bottom of the page. You then insert them in the correct place in the HTML using JavaScript.
Note that you don't have to do one or the other. You could have an infinite scroll that groups the messages by date. Although it might be somewhat harder to implement.
I'm leaving the details out of this answer since that deserves it's own question. Note that you shouldn't create a new question instantly. First have a look around the internet for different libraries or methods to create your own, try to work something out. Then if you get stuck or have a specific question you should create a new question.
One thing you could do is to save the last date in a variable at the end of the outer loop (so after your messages have been printed. Once the condition day != previous_day is met, you print the divisor
You can pass a custom search to pagy in order to display the items in the way you want to be displayed. For example do something like:
#pagy, #messages = pagy(Chatroom.customSearch(params[:q]), items: 20)
In your Chatroom model you can create the customSearch function. Find all chatRoom messages you want, order and send them back to pagy. Hope it helps.

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

Timeline of search/tweets and next_results and refresh_url fileds

My web application should have next/previous results for navigating the search timeline. I already made it by using field next_resultsfor next, and pushing refresh_url into javascript array for "previous" navigating. And it worked then (3-4) days ago. After 1-2 days api calls were not returning field next_results, omitted completely, and today that field is returning same value for all "next" calls, so you are hitting next and you are refreshing the page basically. There are also fields since_id for newer and max_id for older results in search_metadata node, so I can make queries using that values... I could also get those id's from returned tweet objects, and use them, not relying on api search_metadata completely...
So I'm asking if someone already dealt with this, what is the best way to do it, not having to check code every day what twitter-api is returning? I know there is twitter support, I think there are people on this site that has done this. I also have read docs on this.
https://dev.twitter.com/docs/working-with-timelines
https://dev.twitter.com/docs/api/1.1/get/search/tweets
Here is search_metadata node example to ilustrate.
[search_metadata] => Array
(
[completed_in] => 0.057
[max_id] => 4.1747346982858E+17
[max_id_str] => 417473469828583425
[next_results] => ?max_id=416844457594855423&q=place&result_type=mixed
[query] => place
[refresh_url] => ?since_id=417473469828583425&q=place&result_type=mixed
[count] => 15
[since_id] => 0
[since_id_str] => 0
)
Ime Ime, "what is the best way to do it", not sure but this is how I used max_id
present in next_results to fetch tweets from timeline.
Twython search API with next_results
Hope it helps.

Grails gsp pagination not breaks list item

Today when i customize list method of my controller,facing issue in list.gsp page.My problem is that all records are displayed on a single page.
for ex. Suppose i have 15 records then all 15 will show on first page and also there in next link at footer.when clicks on it all pages show same 15 records.
I was customize code because i need to run query and basis of result of query show records on list page.
def query = "from Book where isAvailable = 'true'"
def bookInstanceList = Book.findAll(query)
[bookInstanceList: bookInstanceList , bookInstanceTotal: bookInstanceList.size()]
it shows all records on a single page and records are not paginate on different page.
i want to show maximum 10 records on each page.
please reply me where i am missing.
Thanks in advance
So pagination will not work that way. You are getting your total of the resulting number of rows that were returned, not what would have been returned without pagination.
def bookQuery = Book.where{ isAvailable == 'true' }
[bookInstanceList: bookQuery.list(params), bookInstanceTotal: bookQuery.count()]
params should contain max and offset to implement pagination.

Resources