[掲載日] (更新日) この記事は約 25 分で読めます

Ruby on Rails5でコメント付きブログを簡単に作成する手順

初心者向け無料講座Railsで簡単にブログ風アプリを作成する方法

初心者でもRuby on Railsでブログを作成できる手順を解説します。

  • ブログ作成
  • コメント機能追加
  • デザイン変更

ここまで、簡単にできるので頑張って作成してみましょう。

慣れると、30分以下で作成できるようになります。

目次

Rubyでブログ作成する環境

Ubuntu 16.04.4
ruby 2.5.1
rails 5.0.7

Ubuntu 18でも同様に動作します。
まずはいつも通りにアプリを作成してみます。

Rubyのブログアプリを作成

$ rails new blogapp -d postgresql
$ cd blogapp
$ bundle

いつも通りのコマンドです。
Railsを new でブログアプリを作成している流れです。
ついでにPostgresqlで設定します。

rails new blogapp

このコマンドの意味がわからない場合は、
作成できませんのでもう一度教科書などを見てみましょう。

Rubyのブログを作成する動作を確認

$ rails s -b 192.168.33.10

rails sでも動かせるが、場合によりIPアドレスを指定しないと動かない場合があるので初めからIPアドレスを指定しておくと良いです。

Rubyでブログ風アプリを作成していきます

$ rails g scaffold blog title:string body:text user_name:string user_id:integer

scaffold(スキャッフォルド)するとどうなるかと言うと

  • Create->新規作成(new, create)
  • Read->データ一覧・個別の表示(index, show)
  • Update->データの更新(edit, update)
  • Delete->データの削除(delete)

の必要な画面が一発で作成できます。

これらのことをCRUD(クラッド)って言います。

動作確認とデータベースへ登録を行います

$ rails db:migrate
$ rails s -b 192.168.33.10 
  • scaffold
  • db:migrate

db:migrate データベースマイグレートでデータベースへ登録する作業です。
ここでは scaffold したら、 db:migrate するってことをセットで覚えておきましょう。

db:migrate をやらないとエラー画面がでます

マイグレートしないで出たエラー画面
マイグレートしないで出たエラー画面

Rubyブログアプリを作成した画面の確認

rails s -b 192.168.33.10 で起動したあと
URLに 192.168.33.10:3000/blogs/ と入れてみてください。

blogs/の初期画面

入力画面も出来ています

入力画面
入力画面

一覧画面に詳細・修正・削除のボタンもあります

詳細・編集・削除のリンクもあり
詳細・編集・削除のリンクもあり

Ruby on Railsはたった1行で必要なものは出来てしまいます

たった1行のコマンドを入力するだけで、Rubyブログアプリに必要なもの一式

  • 新規投稿
  • 一覧
  • 詳細
  • 編集
  • 削除

の機能が実装されました。

Rubyブログ作成からデザインを始めます

ここからRuby on Railsで作成したブログアプリの

  • デザイン
  • 見た目

を編集していきます。

編集にはIDEやテキストエディタ―を使いますが、今回はRubyMineを使います。

RubyMineの無料お試しと割引コード

RubyMineは有償ソフトになりますが、試用期間がありますので
1か月間無料でお試しすることができます。

Bootstrap4をCDNで導入します

CDNって聞くとなんか難しそうと思うかもしれませんが、簡単です。
5行コピペするだけです。

ここへ行くと必要なコードをコピペできます。https://getbootstrap.com/docs/4.1/getting-started/introduction/

<!DOCTYPE html>
<html>
  <head>
    <title>Blogapp</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track'=> 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track'=> 'reload' %>
  </head>
  <body>

    <%= yield %>

    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
  </body>
</html>

これだけで、スマホ・タブレット対応のレスポンシブデザインに対応しました。

Rubyでブログのここまでを動画で確認する #1

Rubyブログのヘッダーとフッターをデザインします

<!DOCTYPE html>
<html>
  <head>
    <title>Blogapp</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track'=> 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track'=> 'reload' %>
  </head>
  <body>
  <nav class="navbar navbar-expand-lg navbar-light bg-light">
    <a class="navbar-brand" href="#">Navbar</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>

    <div class="collapse navbar-collapse" id="navbarSupportedContent">
      <ul class="navbar-nav mr-auto">
        <li class="nav-item active">
          <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Link</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
            Dropdown
          </a>
          <div class="dropdown-menu" aria-labelledby="navbarDropdown">
            <a class="dropdown-item" href="#">Action</a>
            <a class="dropdown-item" href="#">Another action</a>
            <div class="dropdown-divider"></div>
            <a class="dropdown-item" href="#">Something else here</a>
          </div>
        </li>
        <li class="nav-item">
          <a class="nav-link disabled" href="#">Disabled</a>
        </li>
      </ul>
      <form class="form-inline my-2 my-lg-0">
        <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
        <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
      </form>
    </div>
  </nav>

    <%= yield %>

  <footer class="container-fluid mt-4 text-center small d-none d-sm-block bg-light">
    <div class="container p-2">
      © 2019 ブログサイト
    </div>
  </footer>
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script>
  </body>
</html>
ヘッダーとフッターをデザインする
ヘッダーとフッターをデザインする

こんな感じでBootstrap4が入っているので簡単にデザインできました。

Rubyブログの他のページもデザインする

indexページのデザイン

<div class="container">
  <p id="notice"><%= notice %></p>

  <h1>Blogs test</h1>

  <table class="table table-striped">
    <thead>
    <tr>
      <th>Title</th>
      <th>Body</th>
      <th>User name</th>
      <th>User</th>
      <th colspan="3"></th>
    </tr>
    </thead>

    <tbody>
    <% @blogs.each do |blog| %>
      <tr>
        <td><%= blog.title %></td>
        <td><%= blog.body.truncate(60)  %></td>
        <td><%= blog.user_name %></td>
        <td><%= blog.user_id %></td>
        <td><%= link_to 'Show', blog %></td>
        <td>
          <%= link_to edit_blog_path(blog), method: :get do %>
            <i class="far fa-edit"></i>
          <% end %>
          <%#= link_to 'Edit', edit_blog_path(blog) %>
        </td>
        <td>
          <%= link_to blog, method: :delete, data: {confirm: 'ほんとうに消しますか?'} do %>
            <i class="far fa-trash-alt"></i>
          <% end %>
          <%#= link_to 'Destroy', blog, method: :delete, data: { confirm: 'Are you sure?' } %>
        </td>
      </tr>
    <% end %>
    </tbody>
  </table>

  <br>

  <%= link_to '新規投稿', new_blog_path, class: 'btn btn-block btn-success btn-sm' %>

</div>

show(詳細)ページデザイン

<div class="container">

  <div class="card my-5">
    <div class="card-body">
      <div class="card-title">
        <h1>
          <%= @blog.title %>
        </h1>
        <div class="text-right">
          更新日<%= @blog.updated_at.strftime("%Y-%m-%d") %> 投稿者<%= @blog.user_id %>: <%= @blog.user_name %>
        </div>
      </div>
      <div class="card-text">
        <%= @blog.body %>
      </div>
    </div>
   </div>

  <%= link_to 'Edit', edit_blog_path(@blog) %> |
  <%= link_to 'Back', blogs_path %>

</div>

edit(編集)とnew(新規投稿)ページのデザイン

<%= form_with(model: blog, local: true) do |form| %>
  <% if blog.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(blog.errors.count, "error") %> prohibited this blog from being saved:</h2>

      <ul>
      <% blog.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= form.label :title %>
    <%= form.text_field :title, class: 'form-control' %>
  </div>

  <div class="field">
    <%= form.label :body %>
    <%= form.text_area :body, class: 'form-control'  %>
  </div>

  <div class="field">
    <%= form.label :user_name %>
    <%= form.text_field :user_name, class: 'form-control'  %>
  </div>

  <div class="field">
    <%= form.label :user_id %>
    <%= form.number_field :user_id, class: 'form-control'  %>
  </div>

  <div class="actions mt-3">
    <%= form.submit "保存する", class: 'btn btn-block btn-success btn-sm' %>
  </div>
<% end %>
デザインした例
デザインした例

Rubyでブログのここまでを動画で確認する #2

Rubyブログのコメント機能を実装する

ここからはブログへコメントできるようにコメント投稿する機能を実装します。

$ rails g model Comment commenter:string body:text blog:references
$ rails g controller Comments
$ rake db:migrate

show(詳細ページ)にコメント機能のコメント欄を追加して表示する

<div class="container">
  <div class="card my-5">
    <div class="card-body">
      <div class="card-title">
        <h1>
          <%= @blog.title %>
        </h1>
        <div class="text-right">
          更新日<%= @blog.updated_at.strftime("%Y-%m-%d") %> 投稿者<%= @blog.user_id %>: <%= @blog.user_name %>
        </div>
      </div>
      <div class="card-text">
        <%= @blog.body %>
      </div>
    </div>
   </div>


  <%= link_to 'Edit', edit_blog_path(@blog) %> |
  <%= link_to 'Back', blogs_path %>

  <h3>コメント</h3>
  <% @blog.comments.each do |comment| %>
    <p>
      <%= comment.commenter %>: <%= comment.body %>
      <%= link_to '削除', [comment.blog, comment],
                  :confirm => 'よろしいですか?',
                  :method => :delete %>

    </p>
  <% end %>

  <h3>コメントを書く</h3>
  <%= form_for([@blog, @blog.comments.build]) do |f| %>
    <div class="field">
      <%= f.text_field :commenter %>
    </div>
    <div class="field">
      <%= f.text_area :body %>
    </div>
    <div class="actions">
      <%= f.submit %>
    </div>
  <% end %>
</div>

routesにコメント機能に必要な記述を追記する

resources :blogs do
  resources :comments
end

コメント機能をコントローラーに追記

class CommentsController < ApplicationController
  def create
    @blog = Blog.find(params[:blog_id])
    @comment = @blog.comments.create(comment_params)
    redirect_to blog_path(@blog)
  end

  def destroy
    @blog = Blog.find(params[:blog_id])
    @comment = @blog.comments.find(params[:id])
    @comment.destroy
    redirect_to blog_path(@blog)
  end

  private
  def comment_params
    params.require(:comment).permit(:body, :commenter)
  end
end

これでコメントの実装が完了しました。

コメント機能のモデルも確認しておく

class Comment < ApplicationRecord
  belongs_to :blog
end

もしこのように記入されていなかったら記入すること。

コメント機能の実装完了
コメント機能の実装完了

こんな感じでコメント投稿画面が出来たと思います。

このままだと詳細ページとコメント欄の見た目がよくないので、デザインをしていきます。

Railsコメント機能のコメント欄のデザインをする

  <h3>コメント</h3>
  <% @blog.comments.each do |comment| %>
    <p>
      <%= comment.commenter %>: <%= comment.body %>
      <%= link_to '削除', [comment.blog, comment],
                  :confirm => 'よろしいですか?',
                  :method => :delete %>

    </p>
  <% end %>

  <h3>コメントを書く</h3>
  <%= form_for([@blog, @blog.comments.build]) do |f| %>
    <div class="field mb-2">
      <%= f.text_field :commenter, placeholder: 'お名前', class: 'form-control' %>
    </div>
    <div class="field mb-2">
      <%= f.text_area :body, placeholder: '本文を入力してください',class: 'form-control' %>
    </div>
    <div class="actions">
      <%= f.submit "投稿する", class: 'btn btn-block btn-success btn-sm' %>
    </div>
  <% end %>

先ほどShowに追加したコメント部分を上記のように変えます。

コメントが付いた記事を消すとエラーになる

このままだとコメントが付いた記事を削除するとエラーになるからモデルに1行付けくわえるだけ

class Blog < ApplicationRecord
  has_many :comments, dependent: :delete_all
end

これで問題なく削除できるようになりました。

Rubyでブログのここまでを動画で確認する #3

Railsで画像を実装投稿する

Railsの初心者から転職・就職するなら

Ruby on Railsの独学に挫折しそうならスクール

挫折しそうなプログラミングなら動画講座。30日間全額返金保証