Creating Simple Blogging Platform - Displaying Posts

By:, On:

This tutorial assumes you have already completed:

  1. Install Ruby on Rails
  2. Create Ruby on Rails application
  3. Create Static Pages - without this deploy will not work
  4. Install Git
  5. Create Remote Git Repository - optional but recommended
  6. Deploy application to Heroku
  7. Manage users with Devise
  8. How to add Twitter Bootstrap to Ruby on Rails application - Advised
  9. Creating Simple Blogging Platform - Creating Model
  10. Creating Simple Blogging Platform - Routes

We have created routes that allow us to type in our browser the address that matches "action" in our "controller." But, what are controllers and actions? In simple terms, controller is the entity on our code that is dedicated to manage certain resource. In our case, it will be posts. Controller is the place where we will decide on the logical interaction between our app and users. Action, on the other hand, is a "subset" of a controller. For example, we will have an action that creates a post.

In our tutorial, we will look at 7 standard actions:

Action Name Role
Show Displaying single record
Index Displaying list of records
New Displaying form new record
Create Saving new record to the database
Edit Displaying form for editing of a record
Update Saving changes made in "edit" form
Destroy Deleting record

Step 1: Create controller

We will look at those one by one as we're building our application, but first lets generate new, empty controller for posts.

bash


$ rails generate controller posts

    create  app/controllers/posts_controller.rb
    invoke  erb
    create    app/views/posts
    invoke  test_unit
    create    test/controllers/posts_controller_test.rb
    invoke  helper
    create    app/helpers/posts_helper.rb
    invoke    test_unit
    create      test/helpers/posts_helper_test.rb
    invoke  assets
    invoke    coffee
    create      app/assets/javascripts/posts.js.coffee
    invoke    scss
    create      app/assets/stylesheets/posts.css.scss

Notice that we are using plural 'posts.' When we were generating model we used singular, capitalized "Post." This is Rails convention.

Quick Tip: For your models' names, always use nouns that have plural forms. Otherwise, controllers and models might have problems communicating properly.

Step 2: Display Posts and Define Action

There are 2 actions that are made for displaying records: "Show" and "Index". First, we will look at index. Open the newly created posts_controller.rb

/app/controllers/posts_controller.rb


class PostsController < ApplicationController
end

We'll start by defining our index action:


class PostsController < ApplicationController

    def index

    end

end

We just added an empty blockthat starts with declaration def index and ends with end like almost anything in rails. Always remember about closing your blocks with end. If you forget to do it, you will evoke an error that looks like this:

Rails throwing error due to lack of 'end' in posts controller

Step 3: Create HTML Template

After we've created the action in the controller, we need to build a HTML template for the action to display. To start, we will create a simple file with one line of HTML inside of the app/views/posts folder and call it index.html.erb:

/app/views/posts/index.html.erb


    <h1>This will be a list of posts</h1>

Because we call the template the same as our action - "index". Rails will match them together so we don't need to specify anywhere that we want these two files to work together. Now, we can restart our application with rails server and open the URL that points to the index: http://localhost:3000/posts

index page

Great, we know that our application works. Next thing we need to do is to actually display all the posts that we have in our database. This is 2 step processes:

  • First: we need to find posts in the database - controller
  • Second: display list as a website - HTML template (view)

Step 4: Modify Controller

Let's open controller and add some code:

/app/controllers/posts_controller.rb


class PostsController < ApplicationController

    def index
        @posts = Post.all
    end

end

@posts - is a name of the variable that we will use to store the posts that we have found in the database. For now, we will just pull all the posts we can find. Of course, we will have to find a better way in case there are a lot of posts in our database. But for now, we're ok with this simple approach.

Step 5: Modify HTML Template

By giving our variable a "@" symbol we've allowed it to travel from controller to the view (HTML template). Therefore, we can now use it to iterate over the list of posts.

/app/views/posts/index.html.erb


    <h1>This is a list of posts</h1>

    <ul>
        <% @posts.each do |p| %>
            <li>
                <h3><%= p.title %></h3>
                <p><%= p.body %></p>
            </li>
        <% end %>
    </ul>

Now head to http://localhost:3000/posts

Website with list of all posts for the database

Step 6: Use Bootstrap

At this point, we can add posts to links in our website menu so we don't need to type URL by hand each time we want to go to the list of posts. We will take an advantage of Bootstrap CSS. In application.html.erb add the following code:

/app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
    <head>
        <title>Demo</title>
        <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
        <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
        <%= csrf_meta_tags %>
    </head>
    <body>

        <% flash.each do |key, value| %>
        <div class="alert alert-<%= key %> alert-dismissable">
            <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
            <%= value %>
        </div>
        <% end %>

        <nav class="navbar navbar-default" role="navigation">
            <div class="container">

                <div class="navbar-header">
                    <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar-collapse-1">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    <%= link_to "Demo App", root_path, class: 'navbar-brand' %>
                </div>

                <div class="collapse navbar-collapse" id="navbar-collapse-1">

                    <ul class="nav navbar-nav navbar-right">
                         <li><%= link_to 'Posts', posts_path %></li>
                         <% if current_user %>
                             <li><%= link_to 'Logout', destroy_user_session_path, method: :delete %></li>
                         <% else %>
                             <li><%= link_to 'Login', new_user_session_path %></li>
                         <% end %>
                    </ul>
                </div>
            </div>
        </nav>

          <div class="container">
              <%= yield %>
          </div>

    </body>
</html>

Step 7: Define Action inside Controller

Let's move on and add a dedicated page to display individual posts. This will be the page where eventually we can add some sort of commenting system.

First, same as before, we need to define action inside the controller:

/app/controllers/posts_controller.rb


class PostsController < ApplicationController

    def index
        @posts = Post.all
    end

    def show

    end

end

Step 8: Match Names

Second, we need the HTML template in /app/views/posts folder that matches name of the action show.html.erb

/app/views/posts/show.html.erb


    <h1>This will be a individual post page</h1>

Step 9: Run Rake Routes

Now, the question is: When users type the address of a post, how do we find the post using that URL? Let's look at the routes that we have previously created:

bash


$ rake routes

    posts GET    /posts(.:format)               posts#index
          POST   /posts(.:format)               posts#create
 new_post GET    /posts/new(.:format)           posts#new
edit_post GET    /posts/:id/edit(.:format)      posts#edit
     post GET    /posts/:id(.:format)           posts#show
          PATCH  /posts/:id(.:format)           posts#update
          PUT    /posts/:id(.:format)           posts#update
          DELETE /posts/:id(.:format)           posts#destroy

Let's have a look at this list closer this time.

Route Name Request Type URI Controller#Action Needs :ID
posts GET /posts(.:format) posts#index no
  POST /posts(.:format) posts#create no
new_post GET /posts/new(.:format) posts#new no
edit_post GET /posts/:id/edit(.:format) posts#edit YES
post GET /posts/:id(.:format) posts#show YES
  PATCH /posts/:id(.:format) posts#update YES
  PUT /posts/:id(.:format) posts#update YES
  DELETE /posts/:id(.:format) posts#destroy YES

Step 10: Understand Columns

The first column shows the path that we can use to create a link. We will add to it either _path or _url to build a link to the index page:


    <%= link_to "All Posts", posts_path %>

We simply took prefix posts added _path to it and rails now knows we want to create a link to controller for posts and action index.

The second column is a method to transfer information between the server and the browser. Basically GET means that the browser "gets" data from the server and anything else (PUT POST PATCH DELETE) is the data going from the browser to the server. For example "edit" gets post form the server. This form will come populated with existing posts title and body. When we click "Save" this will be send to the server to "update" action using PUT.

The third Column is the URI (Uniform Resource Identifier). This is, more or less, what we will see in the URL bar in our browser. One important thing to notice here are all symbols with ":". Those parameters are required by our router in order to point us in the right direction. Let's take edit_post as an example. URI here is /posts/:id/edit(.:format). :id is an identifier of the post itself. We will use it to find the post in the database. For example, if we want to edit post with ID number 124 the URl would be: http://localhost:3000/posts/124/edit.

I have added one column for you to see clearly which action requires passing the parameters with it.

Fourth column indicated which action of which controller the route is pointing to.

Step 11: Use Parameter and Edit HTML Files

With all this information, we can go back to the controller and find our individual post using parameter form URI.

/app/controllers/posts_controller.rb


class PostsController < ApplicationController

    def index
        @posts = Post.all
    end

    def show
        @post = Post.find(params[:id])
    end

end

This time we created variable @post inside of which we save result of a query on all posts using :id as a parameter. This id comes from the URI. We can now use this variable to display the post on its page.

/app/views/posts/show.html.erb


    <h1><%= @post.title %></h1>
    <p><%= @post.body %></p>

Finally, go to the index.html.erb file, we just need to change title of post into a link to the show page.

/app/views/posts/index.html.erb


    <h1>This is a list of posts</h1>

    <ul>
        <% @posts.each do |p| %>
            <li>
                <h3><%= link_to p.title, post_path(p.id) %></h3>
                <p><%= p.body %></p>
            </li>
        <% end %>
    </ul>

Above you can see how we added _pathto postprefix and used p.id to provide param for the link.

If you login you will be able to mark this tutorial as finished to track your progress



Comment

You can login to comment