I myself am just a beginner in the study of RoR, but when developing my own project, there was a desire to make it more convenient using javascript instead of classical pagination using the
will_paginate gem . 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, I have it in English, but I found only bulky and inconvenient options. As they say, you want to do something well - do it yourself. That's what happened.
The pagination will be done using the same will_paginate gem, and we will also use it if javascript is disabled by the user.
So first set the gem:
')
gem 'will_paginate'
bundle install
Then we start with the controller. In my case, this will be a pagination list of users. Accordingly, this action is 'index', 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
Hash session
session[:page]
used as a counter. A little later we will return to it.
Next, go to the index.html.erb view and add the pagination:
<h1>All users</h1> <ul class="users"> <%= render @users %> </ul> <div id="without_button"> <%= will_paginate @users %> </div> <% if @users.next_page %> <div id="load_more_users"> <%= button_to 'More users', {action: "index", new_req: true }, method: :get, remote: true, class: "btn btn-primary btn-large" %> </div> <% end %>
Let me explain a few points. Here we have two blocks. The first c id “without_button” adds a standard gem string for splitting pages. 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 the record. The default for will_paginate is 30 entries. Accordingly, if there are 30 or less, 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 write in css:
#load_more_users { display: none; }
The button transfers control to our action with the
params [: new_req] hash, the value of which we set to true. The explanation will come next.
So now we need to understand that we need to load 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 equal to nil, if true, then we increase the value of the counter by 1. Another point, if javascript is disabled, then pagination will occur through the
params hash
[:] . So we will assign its value to the counter. Hopefully available 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 a new call to an action is taken. But the comrade below correctly noted that the class variable will be common to all users. Therefore, I replaced it with a hash session.
The method must be executed before the index action:
before_action :up_page, only: :index
Now the fun part. Go to CoffeeScript. Add the following code to the file app / assets / javascripts / users.js.coffee
$('#with_button').hide() $('#load_more_users').show() $('#load_more_users form').after('<button class="btn btn-primary btn-large btn-clone disabled" style="display: none;">More users</button>') $('#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 button-clone with a darkened background, which will be shown instead of the first button when it is clicked. In principle, the button-clone is not required here. Instead, you can show the download line or any other image / 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 show our form again with the first button. We create the button-clone in order to prevent the button being pressed again until the records are loaded. Well, we delete our button when all the records from our
ActiveRecord :: Relation array
are already shown.
That's all. I hope this information will be useful to someone.
UPD.: Variable class
@@page
replaced by session [: page]