Limit number of json results - Rails API - ruby-on-rails

I am creating Rails API and when I do get request to mywebsite.com/posts/all it shows me all the post data. I am trying to do mywebsite.com/posts/all?limit=20 to show 20 results or some other number. What is the way to achieve it with rails?

Limit will not work, each time if u call this method it will return only last 20 records,
Best way to achieve this result using pagination, here you can limit number record passing when each request is hitting
You can use gem will_paginate
In controller
#posts = Post.paginate(:page => params[:page], :per_page => 20)
In the view
<%= will_paginate #posts %>
For info about will_paginate
https://github.com/mislav/will_paginate/blob/master/README.md
If u r using API pass params ass below
GET /v1/posts?page=1&per_page=10
Change value in controller
#posts = Post.paginate(page: params[:page], per_page: params[:per_page])

Easy way for this is
#posts = Post.limit(params[:limit])
But you could also use will_paginate gem

Related

Rails kaminari: How to specify total_count for paginate?

COUNT query to find out total_count sometimes very slow.
But if I am caching values of items_amount or such field in model I want to use it for kaminari pagination.
EXAMPLE: I have model
Category (:id, :title, :items_amount)
And then on show view I want to
<%= paginate #items, total_count: #category.items_amount %>
So like paginate_array, but in paginate. It is very useful for perfomance.
Is there a feature like this or how I can add it?
Like will_paginate gem, where we can do it like this
.paginate(page: params[:page], per_page: 72, total_entries: #category.items_amount)
Kaminari just calls the total_count method on #items in order to get the count. By default this does the SELECT count(*) ... query but you could decorate #items to be something that provides your cached count.
If you are just generating page links though then paginate will take a total_pages option. By providing the page count it means that the paginate call doesn't need to get the total count. (I can't find that option explicitly documented but it is in the code and I've tested using it).
paginate #items, total_pages: #cached_page_count
#cache_page_count might have a value like (#category.item_amount / 30.0).ceil in order to get the correct page count with 30.0 being your page size.
I think they answer this really well in their gems readme? https://github.com/kaminari/kaminari
You can do this on controller level using paginates_per to set the limit on each page and max_paginates_per to set the limit of pages?

User-changeable pagination preferably using will_paginate gem

I am using the will_paginate gem and am trying to figure out how to make it so that the user browsing the site can change how many items he/she wants per page using a list, like the list on the right side of this picture
(random google image search).
I'm also new to rails so I would very much appreciate it if you could give me an idea as to where each code would go. Thanks for any help.
in Gemfile
gem 'will_paginate'
in your controller where you want to paginate
class SomeController < ApplicationController
def index
#somethings = Model.all.paginate(page: params[:page], per_page: params[:per_page])
end
end
in your view
<%= select_tag :per_page, options_for_select([5,10,20,50],params[:per_page].to_i),
:onchange => "if(this.value){window.location='?per_page='+this.value;}" %>
With will_paginate you would simply use the per_page option:
#posts = Post.paginate(
page: params[:page],
per_page: params[:per_page]
)
However you should be wary when taking user input and passing it to a SQL query like this. In this case it it prudent to cast the input to an integer:
irb(main):008:0> nil.to_i
=> 0
irb(main):009:0> "gobeligook".to_i
=> 0
per_page = params[:per_page].to_i.zero? ? params[:per_page].to_i : 30
#posts = Post.paginate(
page: params[:page],
per_page: per_page
)

why doesn't will_paginate display the items after the first page? (it's null past page 1)

I am paginating an array #items
Here's the relevant controller part
class StaticPagesController < ApplicationController
def home
if signed_in?
#post = current_user.microposts.build
#activities = PublicActivity::Activity.order("created_at desc").paginate(page: params[:page])
#feed_items = current_user.feed.paginate(page: params[:page])
#items = (#feed_items + #activities)
#items.sort_by! {|item| -item.created_at.to_i}
#items = #items.paginate(:page => 1, :per_page => 10)
else
redirect_to '/signin'
end
end
Basically, this is the line that I'm using.
#items = #items.paginate(:page => 1, :per_page => 10)
I also tried changing that to the code below but didn't work.
#items = #items.paginate(page: params[:page], :per_page => 10)
Inside initializers\will_paginate_array_fix.rb
I have this line
require 'will_paginate/array'
In my view, I am using this
<%= render partial: 'shared/item', collection: #items %>
<%= will_paginate #items %>
It seems to work fine for the first page, but when I click on page 2 or 3 or others, I get a blank. It's null. Anyone know how I can fix this?
I think your problem is that you are building your array by combining activities and feed items, which are already paginated and then your are paginating it again.
For example assume that your activity and feed item models are using the will paginating default which is something like 20 items per page and that there are 15 activities and 12 feed items.
On page 1 you combine this array,take the top 10 and display them. #items had 27 entries so you show links to page 2 & 3. But when you click on that you're trying to load page 2 of activities and page 2 of feed items, which are empty since there are fewer than 20 of each.
In my experience trying to paginating through several collections like this is very tricky (unless you can load all of them and just paginate the array). A "load more items" button is easier because you just have to keep track of what the last cutoff date was

Paginate Multiple Models in Kaminari

I'm creating a search page that will do an application wide search on users, posts, and comments. I currently have:
# POST /search
def index
query = params[:query]
#users = User.search(query).page(params[:page])
#posts = Post.search(query).page(params[:page])
#comments = Comment.search(query).page(params[:page])
respond_to do |format|
format.html
end
end
However I'm really trying to get something where all the results are mixed together then paginated. What are some of the strategies for doing paginated search like this? Thanks!
Ever since this commit: https://github.com/amatsuda/kaminari/commit/f9f529fb68ab89feea38773a4c625c1b14859128
You can do the following
In your view you can do this:
<%= paginate #users, :remote => true, :param_name => "user_page" %>
<%= paginate #posts, :remote => true, :param_name => "post_page" %>
<%= paginate #comments, :remote => true, :param_name => "comment_#{some_post_id}_page" %>
and then in your controller you can refer to them in this way:
#users = User.search(query).page(params[:user_page])
#posts = Post.search(query).page(params[:post_page])
#comments = Comment.search(query).page(params[:comment_page])
and your view's js.erb you might have something like:
$('#posts').html('<%= escape_javascript render(#posts) %>');
$('.table-pager').html('<%= escape_javascript(paginate(#posts, :remote => true).to_s) %>');
Before thinking about a solution, you need to first define exactly what you want the final result to be. If you want to display a few of each type of record on the results page you can modify the approach you posted and combine the three paginated results using:
#results = #users + #posts + #comments
#results.sort! { |a, b| a.score(query) > b.score(query) }
Each object will need to have an instance method 'score' that will let it sort based on the query priority. Also, you will need to modify your view to handle correct rendering of each item and ensure that the pagination is called on the model with the most pages.
Alternatively, a more robust method would be to add a full-text search service (such as Index Tank, Web Solr, Thinking Sphinx). The technology for what's hot for these moves quickly, so do some research and find one that fits your needs. Example syntax for this would be something like:
User.multi_solr_search query, models: [Post, Comment]
You could combine the results from the query and run page on that.
users = User.search(query)
posts = Post.search(query)
comments = Comment.search(query)
#results = users + posts + comments
#results.page(params[:page])

Change number of elements per page with <%= will_paginate %>

I'm using the will_paginate gem. The default is 30 elements per page. How do I customize this?
If your controller is called User, you can do something like this in your controller:
#users = User.paginate :page => params[:page], :per_page => 10, :order => 'name ASC' This will show 10 results per page.
In your view:
<%= will_paginate #users %>
See the per_page option here:
https://github.com/mislav/will_paginate/wiki
It will allow you to change the number displayed per page, for anytime that model is paginated.
For a controller/action specific approach see Raunak's answer.

Resources