“Load More” button using Ajax and jQuery and page pagination in Ruby on Rails
I myself am only new to the study of RoR, but when developing my own project, there was a desire instead of classical pagination using the will_paginate gem to make it more convenient using javascript. This should be a classic button, when clicked, the following n-records are loaded. I did not find a solution to the problem in Russian, there is in English, but I found only cumbersome and inconvenient options. As the saying goes, if you want to do something well, do it yourself. Here's what happened.
We will paginate using the same will_paginate gem, we will also use it if the user has javascript disabled.
So first install the gem:
Then we start with the controller. In my case, this will be a pagination of the user list. Accordingly, this is an 'index' action, which should respond to a javascript (: js) request:
Session Hash
Next, go to the index.html.erb view and add the pagination:
I will explain a few points. Here we have two blocks. The first c id “without_button” adds a standard page break gem line. We will use it when javascript is disabled: The

second block includes a button. It will be shown only if the number of users is enough to break into records. The default for will_paginate is 30 entries. Accordingly, if there are 30 or fewer, the next_page method will return nil and the block will not be loaded. If javascript is disabled, there should be no button. Accordingly, we prescribe in css:
The button transfers control to our action with the hash params [: new_req] , the value of which we set to true. The explanation will be further.
So now we need to understand that we need to download the following entries. Moreover, the counter should be equal to 1 (first page) when loading or updating the page. Here params [: new_req] helps us , until the button is pressed it is nil, if true, then increase the counter by 1. Another point, if javascript is disabled, pagination will occur through the params [: page] hash . So we will assign its value to the counter. Hope accessible explained. So we create the following method:
Initially, I used a class variable as a counter, since it is not re-created as an instance variable when I call the action again. But the companion below correctly noted that the class variable will be common to all users. So I replaced it with a session hash.
The method must be executed before the index action:
Now the fun part. We pass to CoffeeScript. Add the following code to the app / assets / javascripts / users.js.coffee file
The first line hides the classic pagination, the second shows the button. Then, after our button, we add a second clone button with a darkened background, which will be shown instead of the first button when you click on it. In principle, the clone button is optional. Instead, you can show the download bar or any other picture / gif.
It remains to connect Ajax. Add the following code to index.js.erb:
After loading the following user n-records, we hide the clone button and again show our form with the first button. We create the clone button in order to prevent the button from being pressed again until the records are loaded. Well, delete our button when all records from our ActiveRecord :: Relation array are already shown.
That's all. I hope this information will be useful to someone.
UPD .:
We will paginate using the same will_paginate gem, we will also use it if the user has javascript disabled.
So first install the gem:
gem 'will_paginate'
bundle install
Then we start with the controller. In my case, this will be a pagination of the user list. Accordingly, this is an 'index' action, which should respond to a javascript (: js) request:
respond_to :html, :xml, :json, :js
def index
@users = User.paginate(page: session[:page])
respond_with @users
end
Session Hash
session[:page]
used as a counter. A little later we will return to him. Next, go to the index.html.erb view and add the pagination:
All users
<%= render @users %>
<% if @users.next_page %>
<%= button_to 'More users', {action: "index", new_req: true }, method: :get, remote: true, class: "btn btn-primary btn-large" %>
<% end %>
I will explain a few points. Here we have two blocks. The first c id “without_button” adds a standard page break gem line. We will use it when javascript is disabled: The

second block includes a button. It will be shown only if the number of users is enough to break into records. The default for will_paginate is 30 entries. Accordingly, if there are 30 or fewer, the next_page method will return nil and the block will not be loaded. If javascript is disabled, there should be no button. Accordingly, we prescribe in css:
#load_more_users {
display: none;
}
The button transfers control to our action with the hash params [: new_req] , the value of which we set to true. The explanation will be further.
So now we need to understand that we need to download the following entries. Moreover, the counter should be equal to 1 (first page) when loading or updating the page. Here params [: new_req] helps us , until the button is pressed it is nil, if true, then increase the counter by 1. Another point, if javascript is disabled, pagination will occur through the params [: page] hash . So we will assign its value to the counter. Hope accessible explained. So we create the following method:
private
def up_page
session[:page] = case
when params[:new_req] then session[:page]+1
when params[:page] then params[:page]
else 1
end
end
Initially, I used a class variable as a counter, since it is not re-created as an instance variable when I call the action again. But the companion below correctly noted that the class variable will be common to all users. So I replaced it with a session hash.
The method must be executed before the index action:
before_action :up_page, only: :index
Now the fun part. We pass to CoffeeScript. Add the following code to the app / assets / javascripts / users.js.coffee file
$('#with_button').hide()
$('#load_more_users').show()
$('#load_more_users form').after('')
$('#load_more_users').click ->
$('#load_more_users').find('form').hide().siblings('button').show()
The first line hides the classic pagination, the second shows the button. Then, after our button, we add a second clone button with a darkened background, which will be shown instead of the first button when you click on it. In principle, the clone button is optional. Instead, you can show the download bar or any other picture / gif.
It remains to connect Ajax. Add the following code to index.js.erb:
$('.users').append('<%= j render @users %>').siblings('#load_more_users').find("button").hide().siblings('form').show();
<% unless @users.next_page %>
$('#load_more_users').remove();
<% end %>
After loading the following user n-records, we hide the clone button and again show our form with the first button. We create the clone button in order to prevent the button from being pressed again until the records are loaded. Well, delete our button when all records from our ActiveRecord :: Relation array are already shown.
That's all. I hope this information will be useful to someone.
UPD .:
@@page
Replaced the class variable with session [: page]