shimmyShow Webアプリ開発ブログ

プログラミングスクールTECH::CAMPを73期を卒業し、紙媒体で実施されている教育の根本を変えていくためのサービスを開発中。当ブログを読めば誰でも当該サービスを開発できるようにするため軌跡を記録中。

【第3章】オンライン教科書サービス作成【教科書の投稿機能】

目的

第2章ではデータベースにseeds.rbを用いて仮データ登録をしたが、本章では教科書の投稿ページを作成し教科書を投稿できるようにする。

ルーティング設定

config/routes.rbを下記のように実装する。

Rails.application.routes.draw do
  root to: 'texts#index'
  resources :texts, only: [:new] 
end

コントローラーの実装

上記にてnewアクションのルーティングを設定したので、コントローラーにnewアクションを実装していく。
app/controllers/texts_controller.rbを下記のように実装する。

class TextsController < ApplicationController

  def index
    @texts = Text.all
  end

  def new
  end
end

ビューファイル作成

newアクションをコントローラーに実装したので、対応するビューファイルを作成する。
app/views/texts/new.html.erb

<div class="content__title">
  新規テキストの作成
</div>

下図のように表示されれば成功です。

f:id:erwinmarvin:20200916215439p:plain
new.html.erb

トップページに新規テキスト作成のリンクを設定

トップページから新規投稿ページにアクセスできるよう、application.html.erb実装する。
app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>OnlineText</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <header class="header">
      <div class="header__title">
        <%= link_to "OnlineText", root_path, class: "header__title--text" %>
      </div>
      <div class="header__right">
        <%= link_to "新規テキスト作成", new_text_path, class: "header__right--btn" %>
      </div>
    </header>
    <div class="contents">
      <%= yield %>
    </div>
  </body>
</html>

link_to部分の編集を実施した。
ロゴをトップページへ遷移するようroot_pathを設定。
新規テキスト作成ボタンを押下した場合に、新規テキスト作成画面へ遷移するようにnew_text_pathを設定。

インスタンスを生成と新規テキスト作成フォームの作成

app/controllers/texts_controller.rbを下記のように編集する。

class TextsController < ApplicationController

  def index
    @texts = Text.all
  end

  def new
    @text = Text.new
  end

end

app/views/texts/new.html.erbを下記のように編集する。

<div class="content__title">
  新規テキストの作成
</div>

<%= form_with model: @text, class: :form, local: true do |form| %>
  <%= form.text_field :title, placeholder: :テキストタイトル, class: :form__title %>
  <%= form.text_area  :abstract, placeholder: :テキスト概要, class: :form__abstract %>
  <%= form.text_area :body, placeholder: :テキスト本文, class: :form__body %>
  <%= form.submit '作成する', class: :form__btn %>
<% end %>

createアクションの記述をしていないため、下図エラーが発生する。
form_withは自動で次アクションへパスする。
今回の場合、newアクションの次アクションcreateが存在していていないため次がないよ。。。というエラーが発生する。

f:id:erwinmarvin:20200916221746p:plain
error

ルーティング設定

config/routes.rbへ下記のようにcreateを追加する。

Rails.application.routes.draw do
  root to: 'texts#index'
  resources :texts, only: [:new, :create]
end

コントローラーの実装

上記にてcreateアクションのルーティングを設定したので、コントローラーにcreateアクションを実装していく。 createアクションの実装に伴い、ストロングパラメータの実装も行う。
app/controllers/texts_controller.rb

class TextsController < ApplicationController

  def index
    @texts = Text.all
  end

  def new
    @text = Text.new
  end

  def create
    Text.create(text_params)
  end

  private
  def text_params
    params.require(:text).permit(:title, :abstract, :body).merge(public_flag: "1")
  end

end

対象のcssファイルも修正する。
app/assets/stylesheets/texts.scss

body{
  background-color: #f6f6f6;
  min-width: 650px;
  .header{
    height: 56px;
    width: 100%;
    padding: 0 150px;
    background-color: #66FFCC;
    color: #fff;
    display: flex;
    justify-content: space-between;
    &__title{
      font-size: 30px;
      line-height: 56px;
      &--text{
        text-decoration: none;
        color: #fff;
      }
    }
    &__right{
      &--btn{
        text-decoration: none;
        line-height: 56px;
        color: #fff;
        margin-left:15px;
      }
    }
  }
  .contents{
    margin: 30px auto 0;
    background-color: #fff;
    height: 600px;
    width: 70%;
    overflow: scroll;
    .content{
      padding: 10px;
      border-bottom: 1px solid #f6f6f6;
      display: flex;
      &__left{
        padding-right: 20px;
        &--image{
          height: 55px;
          width: 55px;
          border: solid 1px;
        }
      }
      &__right{
        width: calc(100%-100px);
        &__top{
          font-size: 20px;
          font-weight: bold;
          &--title{
            text-decoration: none;
            color: #000000;
          }
        }
        &__bottom{
          font-size: 15px;
          color: #999;
          display: flex;
          &--userName{
            &--btn{
              text-decoration: none;
              color: #999;
            }
          }
          &--date{
            margin-left: 20px;
          }
        }
      }
      &__title{
        font-size: 30px;
        font-weight: bold;
        padding-top: 30px;
        text-align: center;
      }
    }
    .textTitle{
      padding-top: 20px;
      text-align: center;
      font-size: 20px;
      font-weight: bold;
    }
    .textDate{
      font-size: 15px;
      color: #999;
      text-align: center;
    }
    .textAuthor{
      font-size: 15px;
      color: #999;
      text-align: center;
    }
    .textManage{
      display: flex;
      justify-content: center;
      margin-top: 10px;
      &__edit{
        display: block;
        border-radius: 5px;
        color: #ffffff;
        background-color:#66FFCC;
        padding: 0 10px;
        text-decoration: none;
        margin-right: 10px;
      }
      &__delete{
        display: block;
        border-radius: 5px;
        color: #ffffff;
        background-color:#66FFCC;
        padding: 0 10px;
        text-decoration: none;
        margin-left: 10px;
      }
    }
    .textText{
      margin: 20px 30px;
    }
  }
  .form{
    width: 85%;
    height: 100%;
    margin: 0 auto;
    padding-top: 30px;
    &__title{
      display: block;
      width: 100%;
      height: 50px;
    }
    &__abstract{
      display: block;
      width: 100%;
      height: 50px;
      margin-top: 15px;
    }
    &__body{
      display: block;
      width: 100%;
      height: 50%;
      margin-top: 15px;
    }
    &__btn{
      display: block;
      width: 30%;
      margin: 15px auto 0;
    }
  }
  .user{
    padding: 15px 30px;
  }
}

下図のように表示されれば成功です。 f:id:erwinmarvin:20200916223256p:plain f:id:erwinmarvin:20200916223325p:plain

バリデーションの設定

データを登録する際に、制約をかけることをバリデーションといいます。
入力必須の項目に対して空のデータを登録できないようにしたりするために用います。
普段様々なサイトで必須項目ですというエラーメッセージを見たら、バリデーションに引っ掛かったのだなと思ってください。
下記モデルの編集をします。 app/models/text.rb

class Text < ApplicationRecord
  validates :title, :abstract, :body, presence: true
end

教科書の投稿機能の基本的な部分は完了です。
次の章で投稿した教科書の表示機能を説明いたします。