Do you want your rails app to automatically load the next page when scrolled to the bottom? That's what we're covering in this post. We will create a rails app like Pinterest in Rails 6.
Create the Image scaffold.
$ rails g scaffold Image url:string author:string
This will generate the necessary files for the rails app. You don't need to know most of them. We will be editing only some of the files.
To create the image table, run this on your terminal:
$ rails db:migrate
Edit config/routes.rb.
Rails.application.routes.draw do root to: "images#index" end
This way the root page would use image#index by default(localhost:3000).
Edit db/seeds.rb
require "net/http" url = "https://picsum.photos/v2/list?page=2&limit=100" resp = Net::HTTP.get_response(URI.parse(url)) data = JSON.parse(resp.body) data.each do |d| url = "https://picsum.photos/200/#{300+(rand(1..5)*20)}" #This will use random heights for the image p Image.where(author: d['author'], url: url).first_or_create end
The URL, "picsum.photos/v2/list?page=2&limit=100" will return 100 random images that we will be using as seed for our rails app. For more information about this you could check it here.
Then run in your terminal:
$ rails db:seed
Update app/views/images/index.html.erb.
<header class="container"> <h1 class="element-stack">Pinterest Flow</h1> <p class="element-stack">Scroll down to load more data</p> </header> <div id="columns"> <%- @images.each do |image| %> <figure> <img src=<%= image.url %>> <figcaption><%= image.author%></figcaption> </figure> <% end %> </div>
Edit app/assets/stylesheets/images.scss or app/assets/stylesheets/images.css, depending on what's generated by the scaffold.
@font-face{font-family:'Calluna'; src:url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/4273/callunasansregular-webfont.woff') format('woff'); } body { background: url(//subtlepatterns.com/patterns/scribble_light.png); font-family: Calluna, Arial, sans-serif; min-height: 1000px; } #columns { column-width: 150px; column-gap: 15px; width: 90%; max-width: 1100px; margin: 50px auto; } div#columns figure { background: #fefefe; margin: 0 2px 15px; padding-bottom: 10px; transition: opacity .4s ease-in-out; display: inline-block; column-break-inside: avoid; min-height: 100px; } div#columns figure img { width: 100%; height: auto; border-bottom: 1px solid #ccc; margin-bottom: 5px; border-radius: 15px; } div#columns figure figcaption { font-size: .9rem; color: #444; line-height: 1.5; } div#columns small { font-size: 1rem; float: right; text-transform: uppercase; color: #aaa; } div#columns small a { color: #666; text-decoration: none; transition: .4s color; } @media screen and (max-width: 750px) { #columns { column-gap: 0px; } #columns figure { width: 100%; } }
This CSS is from this.
Also import it in application.css.
/* * This is a manifest file that'll be compiled into application.css, which will include all the files * listed below. * * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's * vendor/assets/stylesheets directory can be referenced here using a relative path. * * You're free to add application-wide styles to this file and they'll appear at the bottom of the * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS * files in this directory. Styles in this file should be added after the last require_* statement. * It is generally better to create a new file per style scope. * *= require card *= require_tree . *= require_self */ @import "images";
This is the styling we would be using. You could check out your localhost to check if it is all okay.
Add paginate for images using will_paginate gem. Add this to the Gemfile.
gem 'will_paginate'
Then run bundle install.
$ bundle install
Edit index action in app/controllers/images_controller.rb.
# GET /images or /images.json def index @images = Image.all.paginate(page: params[:page], per_page: 15) end
Create _images.html.erb in app/views/images with this code.
<%- images.each do |image| %> <figure> <img src=<%= image.url %>> <figcaption><%= image.author%></figcaption> </figure> <% end %>
Then edit app/views/images/index.html.erb.
<div id="columns"> <%=render partial: "images", locals:{images: @images} %> </div> <%= will_paginate @images %>
This would make paginate working in our rails app.
Add Jquery to Rails. Run this in your terminal.
$ yarn add jquery
Then add the code below in config/webpack/environment.js.
const webpack = require('webpack') environment.plugins.prepend('Provide', new webpack.ProvidePlugin({ $: 'jquery/src/jquery', jQuery: 'jquery/src/jquery' }) )
Require jquery in application.js file.
require("jquery")
Create jquery.pageless.js in app/javascript/packs with this code
Then require it in the application.js file.
require("jquery") require("packs/jquery.pageless")
Add this code in app/views/images/index.html.erb.
<script type="text/javascript" charset="utf-8"> var totalPages = <%= @images.total_pages %>; var url = '<%= root_path%>'; $('#columns').pageless({ totalPages: totalPages , url: url , loaderMsg: 'Loading more results' }); </script>
Edit app/controllers/images_controller.rb.
def index @images = Image.all.paginate(page: params[:page], per_page: 15) if request.xhr? render partial: 'images/images', locals:{images: @images} end end
Now check your localhost to see if it's running.
And that's it. We're done! ๐
If you want to check the code. You could do it here: Github Repository