Explore our comprehensive Ruby on Rails tutorial that covers how to install the FriendlyId gem, use slugs to create SEO-friendly URLs, and rebuild the product database.
This exercise is excerpted from Noble Desktop’s past web development training materials. Noble Desktop now teaches JavaScript and the MERN Stack in our Full Stack Development Certificate. To learn current skills in web development, check out our coding bootcamps in NYC and live online.
Topics covered in this Ruby on Rails tutorial:
Installing the FriendlyId gem, Using slugs to create SEO-friendly URLs, Rebuilding the product database
Exercise Overview
In this exercise, we will get all our products’ unique images to display. We will also make the product page URLs SEO-friendly. Finally, we will use Markdown to easily convert plain text to HTML.
-
If you completed the previous exercises, you can skip the following sidebar. We recommend you finish the previous exercises (8A–8B) before starting this one. If you haven’t finished them, do the following sidebar.
If You Did Not Do the Previous Exercises (8A–8B)
- Close any files you may have open.
- Open the Finder and navigate to Class Files > yourname-Rails Class
- Open Terminal.
- Type
cd
and a single space (do NOT press Return yet). - Drag the yourname-Rails Class folder from the Finder to the Terminal window and press ENTER.
- Run
rm -rf nutty
to delete your copy of the nutty site. - Run
git clone https://bitbucket.org/noble-desktop/nutty.git
to copy the That Nutty Guy git repository. - Type
cd nutty
to enter the new directory. - Type
git checkout 8B
to bring the site up to the end of the previous exercise. - Run
bundle
to install any necessary gems. - Run
yarn install --check-files
to install JavaScript dependencies.
Setup
Open a browser and navigate to: localhost:3000
Click on any of the products.
-
Notice that the URL is something like: localhost:3000/products/1
While the product URLs are simple, they are not very search engine-friendly. One of the most important things in SEO (Search Engine Optimization), in terms of which keywords Google considers important for your page, is the contents of your URL. A better URL would be one that is relevant to your page content and product (ex. having the product name in it).
There’s a gem called FriendlyId we can use to help out with this.
In the browser, go to: github.com/norman/friendly_id
-
Scroll down to Rails Quickstart and copy this code (don’t worry if the version is newer than what is shown in this book—just copy what you see in the browser):
gem 'friendly_id', '~> 5.3.0'
We need to add this to our Gemfile.
-
For this exercise we’ll continue working with the nutty folder located in Desktop > Class Files > yourname-Rails Class > nutty
If you haven’t already done so, we suggest opening the nutty folder in your code editor if it allows you to (like Sublime Text does).
In your code editor, open nutty > Gemfile.
-
Scroll to the bottom and add the following code (pasting the last line):
# Use FriendlyId for SEO-friendly URLs gem 'friendly_id', '~> 5.3.0'
-
Save the file.
Remember, whenever you install a new gem, you need to stop the Rails server.
Switch to the ruby tab in the Terminal window (the one running the server).
Hit Ctrl–C to stop the server.
-
Install the new gem by typing:
bundle
-
Restart the Rails server by typing:
rails s
Switch to the second tab in the Terminal window.
-
Type the following to fully configure the gem.
rails generate friendly_id rails db:migrate
Using Slugs to Create SEO-Friendly URLs
FriendlyId uses a concept called slugs. You may be more familiar with them as aliases or permalinks. Instead of a numerical id in the URL for each page, FriendlyId lets you create a SEO-friendly URL.
-
First, we need to add a string field to hold this value. In Terminal, type:
rails g migration add_slug_to_products slug:uniq
Note the new ‘uniq’ type for slug. This is a shorthand for a unique string value. Because each slug will represent one URL, it stands to reason that two products cannot have the same slug. Declaring this field as unique ensures that this cannot happen.
-
In your code editor, open nutty > db > migrate > #
_
add_
slug_
to_
products.rbNOTE: The
#
stands for the unique numerical filename, which is the timestamp of its creation and will be different for everyone.Here in this file, we’ll see the following code:
add_column :products, :slug, :string add_index :products, :slug, unique: true
Not only are we adding the column, we are adding an index! What’s that all about?
We need to make sure we put an index on the slug column because an index is very important for performance. Whenever you have a lot of lookups on a field in your database, having an index there will make sure those lookups are as fast as possible. Otherwise, you could start to see significant slowdown in your application as you add more products to your website. Slug will be used constantly for lookups because it’s a substitute for the id field. The unique index ensures the highest performance possible.
Close the file.
-
Switch to Terminal and type:
rails db:migrate
We need to add some logic to the model to make it aware of the slug.
In your code editor, open nutty > app > models > product.rb
-
Add the code shown in bold:
has_one_attached :image extend FriendlyId friendly_id :title, use: [:slugged, :finders] end
NOTE:
:title
is specifying that we want the id to generate from the title field.:finders
is important because it tells FriendlyId to modify the find method to use the new id. Save the file.
-
We need to do something similar for Active Admin. Scroll the bottom of app > admin > products.rb and add the code in bold:
f.actions end controller do scoped_collection.find(params[:id]) end end
In the browser, go to: localhost:3000/admin
Sign in if prompted.
At the top, click on Products.
In order to get the slug to change, we just need to update a product (or create a new one). Find the Buddha Board product (should be at the top).
Under the Id column on the left, click 8.
At the top right of the product page, click Edit Product.
We do not need to change any info; simply click the Update Product button at the bottom.
Check out the URL at the top! The old Id number should be gone and it should now say: localhost:3000/admin/products/buddha-board
Visit localhost:3000/products/buddha-board to see the product page at its new, SEO-optimized URL!
Remaking the Database
Now that we have Active Storage and Friendly ID configured, let’s wipe our database, update our seeds file, and re-import everything. That will ensure we get all our images and slugs in place for all our products, with a minimum of tedious editing, uploading, and re-saving through the admin interface.
The challenge is, how do we programmatically add an attachment to a model object? As long as the image file is accessible from some location on our hard drive or the internet (or really anywhere), it is actually shockingly easy.
In your code editor, open nutty > db > seeds.rb
-
We prepared this seeds file for you. Take note of the following:
- We included some code for the image for each product for your convenience (around lines 16, 29, 40, etc.). We created this seeds file by building an array of products with attributes and an image filename.
- We next have an
each
loop that steps through each product, creates a new product with the given attributes, and saves it. If it saves correctly, it will print to the screen that the product was created.
The only thing we have to add to this is code that looks up the image file and attaches it to the product before we save. Fortunately, that will be very easy.
-
In seeds.rb around line 114, add the code shown in bold:
p = Product.new(product[:attributes]) fn = "public/img/product_images/#{product[:image]}" if File.exist? fn p.image.attach(io: File.open(fn), filename: product[:image]) end if p.save puts "Created #{p.title}" end
We just created a string which holds the path to the file. Then we referenced
p
(the new product object), created a new file object, and added some error checking at the end. -
Save the file.
Now let’s delete all of our product, and seed our database again.
-
Switch to Terminal and type:
rails c
-
In the rails console, type:
Product.destroy_all
Type
exit
to leave rails console and return to the regular command prompt.-
Next, type:
rails db:seed
-
In a browser, go to localhost:3000 (reload it if it’s already open).
All the product images should finally appear. Awesome!
Click the products to view their pages and see that each one now has its own image as well as an SEO-friendly URL. Things are really coming together.