Explore a comprehensive Ruby on Rails tutorial covering crucial topics such as adding dynamic data, rendering a partial, validations, and coding the product index page.
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:
Adding dynamic data, Rendering a partial, Validations
Exercise Overview
Now that we’ve got all of our HTML, CSS, and JavaScript in place, as well as our images and fonts, our next step will be making this content dynamic.
-
If you completed the previous exercise, you can skip the following sidebar. We recommend you finish the previous exercise (B1) before starting this one. If you haven’t finished it, do the following sidebar.
If You Did Not Do the Previous Exercise (B1)
- 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 B1
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.
Coding the Product Index Page
We need to make the products on the main page link to individual product pages.
-
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 > app > views > layouts > application.html.erb
-
You’re going to be selecting a big chunk of code (around lines 62–107). We’ll show you the beginning and end of it:
<div id="featured"> <h2 class="category">Featured Gifts</h2> <hr>
Code Omitted To Save Space
<p class="gray-text">$24.99</p> <div> </div>
There should be 2 closing
</div>
tags left when you’re done. Once selected, cut (Cmd–X) the code.
-
In the space where the code was cut, type this line shown in bold:
<div class="container"> <div id="main" role="main"> <%= yield %> </div> </div>
Save the file.
In your code editor, open: nutty > app > views > products > index.html.erb
Hit Cmd–V to paste the code you previously cut. This code should only appear on this page (the index/overview page for our products).
-
Save the file.
Next, we need to make the products dynamic. We only need one row and we need to iterate over the products.
-
Select another big chunk of code (around lines 11–45). We’ll show you the beginning and end of it:
<div class="col-md-3 col-sm-4"> <a href="#"><img src="img/product_images/finger-tentacles.jpg" alt="Finger Tentacles"></a> <a href="#"><p class="product">Finger Tentacles</p></a>
Code Omitted To Save Space
<a href="#"><p class="product">Buddha Board</p></a> <p class="gray-text">$24.99</p> </div>
Once selected, delete the code.
-
Add the code shown in bold:
<div class="row"> <% @products.each do |product| %> <div class="col-md-3 col-sm-4"> <a href="product.html"><img class="" src="img/product_images/tinfoil-hat.jpg" alt="Tinfoil Hat"></a> <a href="product.html"><p class="product">Tinfoil Hat</p></a> <p class="gray-text">$7.99</p> </div> <% end %> </div>
Every time we have a product, we’re going to print one of these divs.
-
Delete the code shown in bold:
<a href="product.html"><img id="bill" class="" src="img/product_images/tinfoil-hat.jpg" alt="Tinfoil Hat"></a> <a href="product.html"><p class="product">Tinfoil Hat</p></a>
-
Wrap the code in a link to the product by adding the code shown in bold:
<div class="col-md-3 col-sm-4 col-xs-12"> <%= link_to product do %> <img class="" ... alt="Tinfoil Hat"> <p class="product">Tinfoil Hat</p> <% end %> <p class="gray-text">$7.99</p>
-
Around line 10, replace the title
Tinfoil Hat
with this code, which will bring in the individual product’s title:<p class="product"><%= product.title %></p>
-
Around line 12, replace
$7.99
with this dynamic code for the price:<p class="gray-text"><%= number_to_currency product.price %></p>
Save the file.
-
In a browser, navigate to localhost:3000 (reload it if you’re already there).
We left the Tinfoil Hat placeholder image, which might be a bit startling at first! However, notice that the other dynamic content (titles and prices) are correct.
Try clicking on a product. Hmm, we still need to add content for the product pages.
Adding the Product Pages’ Content
In your code editor, open Desktop > Class Files > yourname-Rails Level 2 Class > That Nutty Guy HTML > product.html
-
We’ll be selecting a large chunk of code (around lines 54–146). We’ll show you the beginning and end of it (in bold):
<div id="main" role="main"> <div class="row"> <div class="col-xs-12 hidden-sm hidden-xs"> <ol class="breadcrumb">
Code Omitted To Save Space
</div> </div> </div> </div>
Once selected, copy (Cmd–C) the code.
Close the file.
Open nutty > app > views > products > show.html.erb
Paste the code (Cmd–V).
Save the file.
-
Reload the product page in your browser. (If you closed it, go to localhost:3000 and click on a product.)
Cool, we’ve got a product page! However, the product image link is broken. We need to point it to the right location.
Switch back to show.html.erb in your code editor.
-
Around line 17, edit the image path by typing a
/
in front ofimg
as shown in bold below:<img class="product" src="/ img/product_images/tinfoil-hat.jpg" alt="Tinfoil Hat">
-
Reload the product page in your browser. (If you closed it, go to localhost:3000 and click on a product.)
Cool! The image is working now. We should point out that right now, each product page will currently have the same content. Let’s fix that so each product loads its own individual page.
Return to show.html.erb in your code editor. We need to replace the static data with dynamic data that will update according to the individual product being viewed.
Let’s start by replacing all instances of Tinfoil Hat.-
Go to the following to do a Find and Replace:
- If you are using Sublime Text, go to Find > Replace.
- If you are using Dreamweaver, go to Edit > Find and Replace.
-
Enter the following (the Find and Replace labels may be named differently in your code editor):
Find What: Tinfoil Hat
Replace With: <%= @product.title %>
Click the Replace All button.
-
Now let’s replace the Item numbers. Do another Find and Replace:
- If you are using Sublime Text, go to Find > Replace.
- If you are using Dreamweaver, go to Edit > Find and Replace.
-
Enter the following (the Find and Replace labels may be named differently in your code editor):
Find What: NG45636
Replace With: <%= @product.sku %>
Click the Replace All button.
-
Now for the product price. Around line 23, find this line and highlight the price shown in bold:
<p class="price">$7.99</p>
-
Delete it and replace the number with the following bold code:
<p class="price"><%= number_to_currency @product.price %></p>
-
Around line 40, find the product description and highlight it as shown in bold:
<<div class="tab-pane fade show active" id="details" role="tabpanel" aria-labelledby="home-tab"> <p>Preserve free thought! Protect your mind from dangerous radio waves and other highly-suspect technologies used by suspicious government mind-control programs. Made from durable tin with a comfortable interior lining. Does not protect against visual mind-control tech such as subliminal messages in TV and advertising. You'll need goggles for that.</p> </div>
-
Replace the description by adding the following bold code:
<div class="tab-pane fade show active" id="details" role="tabpanel" aria-labelledby="home-tab"> <%= simple_format @product.description %> </div> <!-- / details -->
-
We need to add the specs. Around lines 43–49, highlight the specs as shown in bold:
<div class="tab-pane fade" id="specs" role="tabpanel" aria-labelledby="specs-tab"> <ul> <li>Made from tin, not aluminum! Don't trust the knockoffs.</li> <li>Comfortable interior lining for extended wear.</li> <li>Guaranteed to protect your mind from bad influences.</li> <li>Secure chin strap.</li> <li>Adjustable band for any size head.</li> </ul> </div>
-
Replace the specs by typing the following code shown in bold:
<div class="tab-pane fade" id="specs" role="tabpanel" aria-labelledby="specs-tab"> <%= @product.specs %> </div> <!-- / #specs -->
-
We need to replace the reviews. Highlight this large chunk of code (around lines 46–82). We’ll show you the beginning and end of it (in bold):
<div class="tab-pane fade" id="reviews" role="tabpanel" aria-labelledby="reviews-tab"> <article> <div class="row"> <div class="col-xs-12"> <h3>Overall Rating:</h3>
Code Omitted To Save Space
<p>I bought this for my brother and he got such a kick out of it! The back of the box is also hilarious! I totally recommend this to anyone looking for a great gag gift!</p> </div> </div> </article> <hr> </div>
-
Eventually, the Nutty staff want us to add reviews to this site. Replace the reviews by typing the following bold placeholder:
<div class="tab-pane fade" id="reviews" role="tabpanel" aria-labelledby="reviews-tab"> Coming Soon! </div>
Save the file.
-
Return to the browser and go to localhost:3000. Click on a product. Now each product’s details appear on their page!
The links at the top still don’t work, however. Let’s fix them.
Fixing the Home Links
In your code editor, open nutty > app > views > layouts > application.html.erb
-
We’ll work on the homepage links for now. Do a Find and Replace:
- If you are using Sublime Text, go to Find > Replace.
- If you are using Dreamweaver, go to Edit > Find and Replace.
-
Enter the following (the Find and Replace labels may be named differently in your code editor):
Find What: index.html
Replace With: /
Click the Replace All button.
Save the file.
In your code editor, open nutty > app > views > products > show.html.erb
-
Do another Find and Replace:
- If you are using Sublime Text, go to Find > Replace.
- If you are using Dreamweaver, go to Edit > Find and Replace.
-
Enter the following (the Find and Replace labels may be named differently in your code editor):
Find What: index.html
Replace With: /
Click the Replace All button.
Save the file.
Reload the product page in the browser. Try clicking on the logo in the top left corner to see that it takes you to the homepage.
Specifying Where the Banner Appears
One other thing, when you’re on a product page, notice the Ready to get Nutty? banner at the top. That should only be on the main page, not on each product page.
In your code editor, open nutty > app > views > layouts > application.html.erb
-
Highlight the following code around lines 52–58:
<div class="jumbotron"> <div class="container"> <h1>Ready to get <span id="nutty"> Nutty?</span></h1> <p>Find clever, witty, and hilarious gifts for That Nutty Guy you know. Guaranteed to make your friends and family smile.</p> <p><span id="gift-icon" class="ir"></span><a href="#">Try out our Gift Finder</a></p> </div> </div>
Cut it (Cmd–X).
-
We’ll replace this with a partial. Type:
<%= render 'shared/get_nutty' %>
This code will render a partial named
get_nutty
in a folder calledshared
(because it may be shared between controllers). They don’t exist yet, so let’s create them. Save the file.
Create a new file.
Paste (Cmd–V) the code into the new file.
Go to File > Save As. In the dialog that appears, navigate to nutty > app > views then click the New Folder button.
Name the folder shared and click Create.
Go into the shared folder if you aren’t already in there.
Name the file:
_
get_
nutty.html.erb-
Make sure it is being saved into the shared folder and hit Save.
NOTE: The names of partials always begin with an underscore, however when you render a partial in the code, you don’t use the leading underscore. Go figure.
-
In your code editor, open nutty > app > views > layouts > application.html.erb
Now we just have to make the header conditional. To do this, we’ll create an instance variable called
@get_nutty
. If it’s set, we’ll render the partial; if it isn’t, we won’t. That gives the decision about whether to render it to the controller. -
Add the code shown in bold (around line 52):
<%= render 'shared/get_nutty' if @get_nutty %>
Save the file.
Open: nutty > app > controllers > products_controller.rb
-
Add the code shown in bold:
class ProductsController < ApplicationController def index @get_nutty = true @products = Product.all end
NOTE: We’re only adding this to the index page (not the show page) because that’s where we want the banner to appear.
Save the file.
In the browser, go to or reload localhost:3000. The banner appears there, as before. Click one of the products. The banner is now gone!
Tweaking the Browser Window Titles
While still in the browser, navigate to a product page.
Notice the title at the top of the browser window (or tab). It says That Nutty Guy which is appropriate for the index page, but each product page should have the name of the product. We can fix this.
Go back to products_controller.rb in your code editor.
-
Add the code shown in bold to create an instance variable for the show page:
def show @product = Product.find(params[:id]) @title = @product.title end
Save the file.
Switch to application.html.erb (nutty > app > views > layouts).
-
Around line 7, add the bold code:
<title><%= @title + ' | ' if @title %> That Nutty Guy</title>
This says that if a title has been set, print out the title plus a separator. Otherwise, if a title has not been set, just print out That Nutty Guy.
Save the file.
Go to or reload localhost:3000 in your browser. The title at the top of the browser window should still be That Nutty Guy. Go to a product page. Now the title at the top should contain the name of the product!
Adding Validations
Finally, we should add some basic validations for our product model.
In your code editor, open: nutty > app > models > product.rb
-
Add the code shown in bold to validate that certain fields exist:
class Product < ApplicationRecord validates :title, :sku, :price, presence: true validates :price, numericality: true end
The first bold line confirms that the title, SKU number, and price are present. The second bold line confirms that the price is a number.
Save the file.
Leave your code editor and Terminal open to continue with them in the next exercise.