Intro to Rails - Building a Blog
In this Rails tutorial we will create a simple blogging application. This application will allow the users to:
- Post new blog entries (title, body, timestamp).
- Edit or delete existing blog entries.
- View all blog entries in reverse-chronological order.
- On post, the system will ensure the user has provided a title.
This module is a simplified version of the Getting Started with Rails guide.
Table of Contents
- Objectives
- Setup Instructions
- Starting the Server
- Scaffolding
- Database Creation & Migration
- Testing the Scaffolding
- MVC Bundles
- RESTful Actions and Routes
- Adding Validation
- Creating the Blog View
- Layouts
- Script Console
Objectives
Upon completion of this tutorial, you should be able to:
- Create a new Rails project from the command line.
- Start and stop the testing web-server.
- Generate a scaffold for a particular MVC bundle.
- Prepare your project database using Rake.
- Edit and modify a view associated with a controller action.
- Add simple validation to a model.
- Interact with a model via the console.
*MVC = Model View Controller
Setup Instructions
Let’s create a new Rails project named ‘blog’.
- In your WSL terminal type:
rails new blog
This command will generate a ‘blog’ folder along with a number of sub-folders and files. Your Rails application ‘exists’ within these folders and files.
Be sure to run this command from inside the folder where you wish to place your application folder.
Starting the Server
Now we’ll run the built-in test web-server:
- Open a second console window, navigate to your ‘blog’ folder and type:
rails s
- Load the default welcome screen for your application here:
The command you ran above tells Ruby to launch an HTTP Web Server through which you can test your Rails application. The name of the server you launched is Puma.
Resources
Scaffolding
Let’s tell Rails to scaffold us up an MVC-bundle for a blog post:
- From the command line type:
rails generate scaffold Post title:string body:text
Here we’ve specified that we wish to generate a scaffold named ‘Post’. We have further specified that each post contains a ‘title’ (which is a string) and a ‘body’ (which is a text blob).
We’ll see later on that by Rails will also add a ‘created_at’ and ‘updated_at’ property to each post.
The scaffold generator takes the name of the model (the resource) and optionally a list of field names and types.
Files generated as a result of the scaffolding:
\blog\app\controllers\posts_controller.rb
\blog\app\views\posts\index.html.erb
\blog\app\views\posts\show.html.erb
\blog\app\views\posts\new.html.erb
\blog\app\views\posts\edit.html.erb
\blog\app\views\posts\_form.html.erb
\blog\app\models\post.rb
\blog\app\helpers\posts\_helper.rb
\blog\db\migrate\001_create_posts.rb
Amongst others…
Database Creation & Migration
The default Rails database is SQLite. Let’s create the database table where we will store our blog posts:
- From the command line type:
rails db:migrate
This command creates a new ‘posts’ table in your database. This table will contain five columns:
- id (Auto-incrementing integer index)
- title (string)
- body (text blob)
- created_at (timestamp created automatically)
- updated_at (timestamp created automatically)
📣 Note: Even though we created a scaffold for ‘Post’ (singular) the table created by Rake was named ‘posts’ (plural). This is a Rails standard. The controller and the views will also reference ‘posts’ (plural).
If you want to better understand the DB Migration you should investigate the following file from within your blog project folder:
blog\db\migrate\001_create_posts.rb
(In the place of 001 in the filename will actually be a long timestamp.)
This file was created when you ran the scaffolding command. It details (in Ruby) the database table associated with the scaffolded resource.
Resources
- Rails DB Migrations (Rails Guides)
- SQLite @ Wikipedia
- SQLite.org
Testing the Scaffolding
We should now be able to load our posts controller:
We can even add a new post by click on the ‘New post’ link.
MVC Bundles
When we created the Post
scaffolding, Rails created a posts
controller with a number of actions to allow for CRUD tasks within our posts
table in the database.
For example, the index
action fetches all posts from the model. This action is accessible via the following url:
http://127.0.0.1:3000/posts/
This index action has an associated view to display the posts:
blog\app\views\posts\index.html.erb
The controller uses the Post
model to access the posts
table in the database:
blog\app\models\post.rb
Resources
- Rails Controllers Overview (Rails Guides)
RESTful Actions and Routes
All controller methods represent actions that are accessible via a URL. Each action has an associated view. The scaffolding creates an index
, show
, new
, edit
, create
, update
and destroy
action along with associated routes. These are called the seven RESTful actions/routes.
For example, the ‘new post’ action is found in the new
method of the posts
controller.
The posts
controller can be found here:
blog\app\controllers\posts_controller.rb
Its new
action is accessible via the following URL:
http://127.0.0.1:3000/posts/new
The associated view is located here:
blog\app\views\posts\new.html.erb
Resources
Adding Validation
Let’s add some simple validation to our blog posting.
- Open the
Post
model located here:blog\app\models\post.rb
The Post
class defined in this file allows us to interact with our posts
table in the database. It is currently empty, but it inherits the database functionality from the ActiveRecord::Base
class (by way of the ApplicationRecord
class).
- Add the following line inside the
Post
class:
validates :title, presence: true
Now, before a post can be added to the posts
table Rails will ensure that the user has specified a title. Try adding a new post without a title.
Resources
- Active Record Validations (Rails Guides)
Creating the Blog View
Let’s edit the posts
controller’s index
view to make this look more like a real blog. Open the following file:
blog\app\view\posts\index.html.erb
Ruby code is embedded into this view within <%
and %>
tags. If we want to print a string from Ruby into the HTML we use <%=
and %>
.
The @posts
variable was ‘given’ to our view by the index
action of the posts
controller. Notice that we are using a for-in loop to display all posts. The view will be more ‘blog-like’ if the posts are shown in reverse chronological order.
Replace the current index
view with the following, and study this code until you can sing it blindfolded. Notice how the post title
and body
are accessed. What does the link_to
method do?
<h1>Our Blag</h1>
<br />
<% @posts.each do |post| %>
<h2> <%= post.title %> </h2>
<p> <%= post.body %> </p>
<p>
Created at:
<%= link_to post.created_at, post %>
- <%= link_to 'Edit', edit_post_path(post) %>
- <%= link_to 'Destroy', post, :confirm => 'Are you sure?', :method => :delete %>
</p>
<hr />
<% end %>
<br />
<%= link_to 'New post', new_post_path %>
To ensure that blog posts appear in reverse-chronological order, edit the index
action of the posts
controller. Modify the line where the @posts
variable is created to look like this:
@post = Post.order("created_at DESC")
Resources
Layouts
You may have noticed that the views associated with controller actions are not complete HTML files. This is because each view is inserted inside an HTML layout shell before it is displayed. The layout for your application can be found here:
\blog\app\views\layouts\application.html.erb
The each view is inserted into a layout before the HTML is sent to the user’s browser. The view is inserted where the layout reads:
<%= yield %>
The layout yields to a particular view; how very polite, proper and posh! Try putting some extra marking in the layout and then navigating around your app.
Resources
- Rails Layout and Rendering (Rails Guides)
Script Console
The Rails console allows us to interact with our project models.
- From a command prompt type:
rails c
(Ensure that you are in your project’s root folder.)
From the console try playing around:
p = Post.all # Ask the Post model for all posts.
p[0].title
first = Post.first
new_post = Post.new title: 'Hello from Console', body: 'This is a test'
new_post.save # Save our new post to the database.
Post.all
A second way to add from the console:
Post.create title: 'Another Console Post', body: 'Second console body text.'