Will_Paginate Gem With Rails Displaying Results In Wrong Order - ruby-on-rails

Attempting to sort an entry by an associated field, unfortunately when paginating with Will Paginate the sorting is wrong.
#categories = Category.includes(:posts)
.page(params[:page])
.order("posts.post_at DESC")
I have tried many variations, but unfortunately will paginate does not seem to respect the sort order of categories. Without the pagination the categories are sorted correctly.
How can I get Will Paginate to respect the order?
The end goal is Categories sorted by posts.post_at and paginated while maintaining that order.
Thanks.

Try
#categories = Category.includes(:posts).order("posts.post_at DESC").paginate(:page => params[:page], :per_page => 10)

Sorry can't comment due to low rep, but what are you trying to sort by and what do you want listed?
If you want categories in a certain order with the associated posts, is that by alphabetical?
#categories = Category.includes(:posts).order('categories.name??').page(params[:page])
Category with most recent posts?
#categories = Category.includes(:posts).order("posts.post_at DESC").page(params[:page])
Or are you wanting the most recent posts with the categories listed along with it?
#posts = Post.includes(:category).order('posts.post_at DESC').page(params[:page])
It's unclear what your end goal is with this query.

Related

Cannot get will paginate total_entries to work, rails

The problem is I would like to limit the number of results to say 30, so I put in
controller
#users = User.user_search(params[:name], params[:gender]).paginate(page: params[:page], per_page: 20, total_entries: 30)
render 'user_results'
Say I only get 1 or 2 results back, I will still get pagination for two pages. ie will paginate seems to get the result of how many times the total_entries will divide in to the per_page value. So if I set per_page: 20, total_entries: 110 it will give me six links adding the extra 10 as a page also.
My User.user_search method in the User model is
def self.user_search(a, b)
users = User.all
users = User.where('LOWER (name) LIKE LOWER(?)', "%#{a}%") if a.present?
users = users.where('LOWER (gender) LIKE LOWER(?)', "%#{b}%") if b.present?
return users
end
I have seen people with problems about using join models and will paginate but I am just using simple single model paginate. Searched lots about this. From my knowledge will paginate is passing on total_pages method to view and rendering this results. Is there a way to set a limit to my results?
The total_entries option just is a shortcut to avoid will_paginate querying the count for the results. So if you really want to limit the number of results shown in will paginate, but not mess up with the pagination results when there are only a few results you can do something like this:
total_records = User.user_search(params[:name], params[:gender]).count
total_entries = total_records > 30 ? 30 : total_records
#users = User.user_search(params[:name], params[:gender]).paginate(page: params[:page], per_page: 20, total_entries: total_entries)
render 'user_results'
You might think that this adds an additional query, but will_paginate was still going to do the count query in order to do its logic, here we're just overriding the total_entries by setting a max number of records to show.
Note however that by doing this you'll still get more records in the last page (if the result of dividing the total_records between the pages is not exact), or it might even be possible to ask for a higher page number and still get the 'hidden' results.
If you really need to avoid showing results over a certain number, you'll be forced to use a subquery like this:
#users = User.where(id: User.user_search(params[:name], params[:gender]).limit(30).map(&:id)).paginate(page: params[:page], per_page: 20)
However, this might cause issues if instead of 30 you use a very large number.
Previously I was suggesting using ActiveRecord::QueryMethods.limit, on the search result, but will_paginate overwrites this logic when paginating.

Rails - Combining will_paginate and ransack

I am using Ransack for Filtering and will_paginate for Pagination and it seems I have a problem combining both.
Analyzing memory problems of my app I saw that my Category controller was loading all entries from the database at each call.
def index
#q = Category.all_cached.paginate(:page => params[:page], :per_page => 30).ransack(params[:q])
#categories = #q.result(distinct: true)
end
In order to get the only the first entries for each page I tried the following change:
def index
#q = Category.paginate(:page => params[:page], :per_page => 30).ransack(params[:q])
#categories = #q.result(distinct: true)
end
Problem is that now the pagination is not working any longer.
Error says: Couldn't find Category with 'id'=x even though enough records are available.
I have two questions:
How can I avoid loading all entries at first call but instead per
page
As I also retrieve information about different products in
the category and I want to avoid n+1 calls, how can I add this
[includes(:product)] into the Category Controller?
Try this way:
def index
#q = Category.paginate(page: params[:page], per_page: 30).ransack(params[:q])
#categories = #q.result(distinct: true).includes(:products)
end

Pagination with Rails 5 - Having two models on "newsfeed" and paginating the total?

I am building a web app that has a "newsfeed" with two models (called Event and Suggestion). Is it possible to paginate the newsfeed such that the pagination applies to the total and not either individually? Here is what I have so far in my controller. I tried simply adding the two, though that doesn't work because the result is an array, not an ActiveRecord Association. Thanks in advance!
def index
#ideas = Suggestion.paginate(:page => params[:page], per_page: 25).order('created_at DESC')
#ideas += Event.paginate(:page => params[:page], per_page: 25).order('created_at DESC')
render :index
end
Assuming you use 'will_paginate', try this. Put this in your initializers:
require 'will_paginate/array'
then you can do things like this:
#objects = (Suggestion.all + Event.all).sort_by &:created_at
#objects.paginate(:page =>params[:page], per_page: 25)
The problem here is performance. This way you will get all records from the database every time, and then perform pagination

How to get a unique list of associated results?

I want to search for a Product and get all the categories from all the products from the search result to create a filter interface like github (The "Languages" menu in the sidebar).
#products = Product.product_search(params[:q])
#categories = ?
I want to list all categories from the products in the #products array.
Any idea whats the best way to do this?
I think this should do the trick.
#categories = #products.map(&:category).compact.uniq

How do you use Kaminari to paginate a page by a number value?

I've set up Kaminari so that it can accurately paginate by post title if i do this:
def index
...
#posts = Post.order('title').page(params[:page]).per(5)
...
end
i also have <% paginate %> in the view
but if I try something like this
#posts = Post.order('pageviews').page(params[:page]).per(5)
it stops working. There are no bugs or errors, but it just appears to be sorted arbitrarily. Possibly by date. How come?
Firstly, is it correctly sorted without Kaminari?
I mean, how is Post.order('pageviews') sorted?
Next, can you check the output SQL?
How is it sorted if you run
Post.order('pageviews').page(1).to_sql
result on your DB console?
May be you need desc at order clause? because currently it will order 0 views first.
Post.order('pageviews desc')

Resources