- Read Tutorial
- Watch Guide Video
This guide walks through a step by step process for building out an index action from scratch to list out all of the portfolio items from the database.
Looking at our task list in PivotalTracker, the next item is to build out the portfolio functionality. This is a big feature, and it will take us more than one guide, especially because I am going to be explaining what I am doing throughout the process.
Switch over to the terminal and use the clear command.
Dissecting our Portfolio Item
First we are going to discuss what a portfolio item is.
Open the rails console with the imperative rails c
, and type the command Portfolio.last
. This will bring up the last portfolio item create. This will return a title, subtitle, a body, a main image and thumb image.
Most of that is probably review, but I just wanted to give this quick glimpse at what kind of data we will be dealing with, and now we can discuss how we will actually use the data.
Go ahead and start the rails server rails s
so we have that up and running.
Now, go into sublime and open your controller/portfolios_controller.rb
file. (If you have other files open you can close them at this time). Also, open your routes.rb file (remember you can use command + t to do a fuzzy search: type in routes.rb and easily open the file),
Rails.application.routes.draw do resources :portfolios get 'pages/home' get 'pages/about' get 'pages/contact' resources :blogs
Notice that we have resources:portfolios
. These are the routes that were provided via the portfolio resources generator.
However, if you go back to our controller file, you'll find that it's empty.
class PortfoliosController < ApplicationController end
We are going build this controller one step at a time. If you want a sneak peak, you can look at blogs_controller.rb
to get an idea of what we're going to create. In fact, we're going to be mimicking what the scaffold did for blogs as we create our portfolio controller. If you think that is a duplicate effort, you are correct to some extent, in respect to what the end result will be. However, the goal of this course is for you to learn how Rails works. With that in mind, I want to really dissect and dive deep into building this functionality, and the best way to do that is to break it down and build it out ourselves.
Building a Controller from the Ground Up
The first thing I'm going to do is create an index action
.
class PortfoliosController < ApplicationController def index end end
Typically, an index action is used when you want to list out a number of items. In this case, we're going to list out all the portfolio items. We could name our variable ‘@portfolios’, however I personally prefer to use @portfolio_items
because it is a more logical reference to what we want to display. We will set it equal to Portfolio.all
def index @portfolio_items = Portfolio.all end
In the concept of Model-View-Controller architecture, Portfolio.all
is calling the model inside of the controller and the variable @portfolio_items
is making the data available to the view.
Let’s see what happens when we try to run this. Head to the browser and navigate to localhost:3000/portfolios. This will give an error
It's an explicit error, that indicates the index action is missing a template for this request.
This error is expected because if you go to the views folder, you'll see that while there is a directory called portfolios, it is empty. To fix this, we need to create a new file. It is very important that we name the file index.html.erb
. (Developers note: to create a file right click on the directory and choose new file then give it the appropriate name)
Inside the file, let's create a tag for a heading called "Portfolio Items".
<h1>Portfolio Items</h1>
Save your file and then refresh the browser, you'll see:
To get the data to this page, we can simulate what we did with our blog data on our home page, where we are displaying blogs and skills. However, we're going to do something slightly different. Instead of dispensing the data to the web page and showing all of it, let's display items.
For this, I'm going to use the angle bracket followed by the percent sign <%
(that denotes the beginning of Ruby code). Next I want to call the portfolio items <% @portfolio_items
Looping with Blocks
Now, what I actually want to do is loop over @portfolio_items
. If you go to the localhost:3000/pages/home you'll see “ActiveRecord::Relation" at the beginning of Blogs display. In Rails, this means that this relation is an array of items. These are hashes, or in other words, of hash data type. In order to access the items we need to loop through them and grab each item.
Thankfully, Rails makes that quite easy to do. In Rails we use the word each
to loop over the items. The word do
is used to create a block in Ruby. We'll cover this concept in more depth later, but for now, just know that when we have a process we want to run, this each
, do
code will apply that process to every item in the hash.
<h1>Portfolio Items</h1> <% @portfolio_items.each do
Remember in our seeds file to create the sample data, we used do
in a similar way with the following block:
10.times do |blog| end
So, any time you see the do
and end
in Ruby, the code within the block will run a number of times, which in this case is 10.
In our portfolio_items
code, the loop will run nine times, or, the amount of times equal to the number of portfolio items in the database. The block variable we will use is |portfolio_item|
, technically, you can call it anything, but I think this name makes the code more intuitive. I'm going to end the line with %>
<h1>Portfolio Items</h1> <% @portfolio_items.each do |portfolio_item| %>
This code is embedded ruby, which is what the erb
stands for in the file name. We also need to tell Ruby where the block ends, and we do that with the code <% end %>
So, this is a complete block:
<% @portfolio_items.each do |portfolio_item| %> <% end %>
Processing vs Rendering
Now, if you save your file and switch over to the browser and hit refresh on the "localhost:3000/portfolios" page, nothing is going to be displayed. The reason for this is the formatting. I do not have an =
sign after <%
.
Compare what we have here with what we find by looking at blog/index.html.erb
. Take note of the items inside the <td>
tags, you will see the difference.
<tbody> <% @blogs.each do |blog| %> <tr> <td><%= blog.title %></td> <td><%= blog.body %></td> <td><%= link_to 'Show', blog %></td> <td><%= link_to 'Edit', edit_blog_path(blog) %></td> <td><%=link_to 'Delete Post', blog, method: :delete, data: { confirm: 'Are you sure?' } %></td> </tr> <% end %> </tbody> </table>
Without the =
sign, the Ruby code will only be processed, it will not be rendered on the page. Both of these examples<% %>
, <%= %>
are embedded ruby. However, without the equal sign, the ruby code is just iterating in the background, and that's why it is not showing anything on the page. To get the data to display, we have to implement a bit more code.
Just to make it look a bit more attractive, I’m going to put the display items in paragraph tags. First, we'll display the title of each portfolio item. <p><%= portfolio_item.title %></p>
One little tip here is to go to view < layout < column 2 to split the screen. This way we can have our schema.rb file open at the same time and easily see the portfolio item attributes.
Another tip is that you can easily duplicate a line of code in sublime text by pressing COMMAND+SHIFT+D. Then, in the subsequent lines, simply change the attribute name.
<h1>Portfolio Items</h1> <% @portfolio_items.each do |portfolio_item| %> <p><%= portfolio_item.title %></p> <p><%= portfolio_item.subtitle %></p> <p><%= portfolio_item.body %></p> <p><%= portfolio_item.thumb_image %></p> <% end %>
Now, I don't want to put my main image on the portfolio display page, just the thumb image.
If you refresh the browser, you can see all your portfolio items.
One thing that's not working here is our thumb image. We want to display an image, and not a URL. To fix that, we need to change the paragraph tag to an image tag, like this:
- <p><%= portfolio_item.thumb_image %></p> + <%= image_tag portfolio_item.thumb_image %>
Save the file and refresh your browser and you'll see the image.
Don't worry if image_tag
doesn't make sense right now. We have a whole section dedicated to images in Rails. Meanwhile, just know that it's a method that takes a URL as its parameter, and the method will render an image for us.
So now, everything is working perfectly as we have our title, sub title, body and thumb image. We're not going to worry about styling these until we get to our styling section. For right now this is our Portfolio index action. We have portfolio items, and we can call the portfolio items any time now.
Before we go, let's add the new files to our branch on GitHub.
Let’s start with a git status
You can see that we added an item to portfolio and updated the controller.
We will add our changes with git add .
Then a git commit -m ‘Integrated index action for portfolio items’
Last we will push our code with git push origin portfolio-feature
In the next guide, we're going to see how to start creating new portfolio items and the things we need for that such as forms.