Recently I needed to add infinite scroll to a list view on a Rails app I’m working on. It turned out to be pretty straightforward, so here are the steps I took to get it working.

This tutorial assumes use of Sprockets, haml, and coffee. However most of the following code is trivial to convert if you aren’t using these helpers. I’m also referencing a Post model, but again, if you’re using a different class all you need to do is replace any reference to Post with your class.

You can view a demo app made using this tutorial here, and you can also clone it on github.

First you’ll need to add the will_paginate gem to your project, and include the jquery.inview plugin (put this in the vendor/assets/javascripts folder).

Gemfile

application.js

After that, add a per_page parameter to your model. For example, in post.rb:

Then, in your controller, replace the query with a paginated query, and add format.js to the format response. I’ve included an example showing how to add pagination to the index view, and also how to add it to a scoped query. For example, in posts_controller.rb:

You’ll need a partial that renders your items. For simplicity, I’ve created a shared partial called _posts.html.haml in the shared folder:

Edit your template and add a Load More link. For example, in index.html.haml. We’ve included a test to see if there actually is a next page of content, if not – don’t display the Load More link.

Then create your js template, index.js.haml. Notice that the same next_page method is called on the posts to hide the Load More link when there’s no more content.

And finally add the javascript to load posts automatically when the Load More link is in view, in posts.js.coffee

And you’ll be good to go! This is all you need to do to add pagination with infinite scroll. If you have any problems, check the demo app and see if you can find any differences.

As a reminder, don’t forget that if you’re using Rails 4 turbolinks (which is on by default in Rails 4), you cannot use the shorthand coffeescript version of document ready as I have above in posts.js.coffee (which looks like this: $ ->). Instead, you need to bind the ready code to the page:change turbolinks event, otherwise the code will only work on a hard refresh and not a turbolinks load. You can do this by replacing $ -> with $(document).on ‘page:change’, ->.

If this post has helped you out, feel free to consider throwing a small donation my way.