In this Rails tutorial we will create a simple blogging application. This application will allow the users to:
Upon completion of this tutorial, you should be able to:
*MVC = Model View Controller
This course module was originally created for Rails 2.3.x it was then updated for use with Rails 3, with future refactoring for Rails 4, 5 and 6.
If you notice anything that needs to be changed, please let me know.
When all else fails reference the following two resources:
It is highly recommend that you read through the Getting Started with Rails guide.
Let’s create a new Rails project named ‘blog’:
rails new blogThis 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.
Now we’ll run the built-in test web-server:
rails server
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.
Let’s tell Rails to scaffold us up an MVC-bundle for a blog post:
rails generate scaffold Post title:string body:textHere 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.rbAmongst others…
The default Rails database is SQLite. Let’s create the database table where we will store our blog posts:
rails db:migrateThis command creates a new ‘posts’ table in your database. This table will contain five columns:
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.
We should now be able to load our posts controller:
We can even add a new post by click on the ‘New post’ link.
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
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.
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
Let’s add some simple validation to our blog posting.
Post model located here: blog\app\models\post.rbThe 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).
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.
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")
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!
The Rails script console allows us to interact with our project models.
rails console(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.'
Every time we interact with a controller action Rails generates a log message. These messages show any errors that may occur, along with all the SQL generated by our models when interacting with the database.
Since our server is running in the default development mode, the log file is located here:
blog\log\development.log
The logs will also be shown in the terminal window where you are running the rails server.
We can also inject custom messages into our logs from our controllers or models as follows:
logger.warn "WARNING: This is a custom log message."