fluid_27’s blog

勉強した内容をアウトプットするためのブログ

ブログアプリ作成③ ログイン画面を作る

超初心者がスクールの教材やネット検索を駆使して、不格好なブログアプリを作成する道のり その3

 

 

ログイン画面をカスタマイズ

 

deviseのログイン画面をカスタマイズするためレイアウトファイルを独立させる。

下記の手順にしたがって設定していく。

 https://github.com/plataformatec/devise/wiki/How-To:-Create-custom-layouts#application--devise-config

 

ログイン画面のhtmlを編集できるようにコマンドでdeviseのviewを生成する。

rails g devise: views

を実行

 

 

コントローラごとにレイアウトを指定

次に config/application.rb に

config.to_prepare do

  Devise: :SessionsController.layout "devise"

  Devise: :RegistrationsController.layout "devise"

  Devise: :ConfirmationsController.layout "devise"

  Devise: :UnlocksController.layout "devise"

  Devise: :PasswordController.layout "devise"

  HomeController.layout "home"

end

を書き加えます。

コントローラ名.layout "使うレイアウトファイル"

どうやら、この記法でコントローラごとにレイアウトファイルを指定できるようです。

ただ、この場合指定するレイアウトファイルは

 app/views/layouts

の中になければいけない、とのこと。

 

home_controllerレイアウトを作成していく

 app/views/layouts/home.html.erb を作成

そこに

<!DOCTYPE html>

<html>

   <head>

      <meta name="viewport" content="width=device-width, initial-scale=1.0">

      <title>TODO App</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>

      <%= render "layouts/header" %>

      <%= render "layouts/flash" %>

      <main class="bg-home d-flex align-items-center w-100 h-100">

         <div class="container">

            <%= yield %>

         </div>

      </main>

      <%= render "layouts/footer" %>

   </body>

</html>

を記述

ただ、ここで分からない記述がいくつかあります。

<%= csrf_meta_tags %>とは…

 クロスサイトリクエストフォージェリ(CSRF)というものの対策のために記述するものだそうです。

 クロスサイトリクエストフォージェリとはWebアプリケーションに存在する脆弱性を利用した攻撃方法のことで、掲示板や問い合わせフォームなどを処理するWebアプリケーションが、本来拒否すべき他サイトからのリクエストを受信し処理してしまうこと。

 

<%= csp_meta_tag %>とは…

 クロスサイトスクリプティング攻撃を緩和するコンテンツセキュリティポリシー

 (Content Security Policy: CSP)を実装するもの。

 

 

次はdeviseのコントローラ用のレイアウトを作成

app/views/layouts/devise.html.erb を作成し、下記を記述

<!DOCTYPE html>

<html>

   <head>

      <meta name="viewport" content="width=device-width, initial-scale=1.0">

      <title>TODO App</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>

      <%= render "layouts/header" %>

      <%= render "layouts/flash" %>

      <main class="bg-home d-flex align-items-center w-100 h-100">

         <div class="container">

            <div class= "row">

               <div class= "col-11 col-lg-5 jumbotron mx-auto mt-4" style="box-shadow: 0 0 5px 5px rgba(0, 0, 0, 0.2)">

                  <%= yield %>

               </div>

            </div>

         </div>

      </main>

      <%= render "layouts/footer" %>

   </body>

</html>

 

 

ログイン状況によってヘッダの表示が変える

 app/views/layouts/_header.erb の header内に下記を記述

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

   <ul class="navbar-nav ml-auto">

      <% if user_signed_in? %>

         <li class="nav-item">

            <%= link_to "Log out", "destroy_user_session_path, method: :delete, class: "nav-link" %>

         </li>

      <% else %>

         <li class="nav-item">

            <%= link_to "Sign up", new_user_registration_path, class: "nav-link" %>

         </li>

         <li class="nav-item">

            <%= link_to "Log in", new_user_session_path, class: "nav-link" %>

         </li>

      <% end %>

   </ul>

</div>

上記はif文とuser_signed_in? というヘルパーメソッドで実装

 

Railsのフォームとdeviseにbootstrapのクラスを適用するため

app/asetts/stylesheets/forms.scss を作成し、下記を記述

div.field {

   @extand .form-group !optional;

   input[type="text"],

   textarea,

   select,

   input[type="email"]

   input[type="password"] {

      @extand .form-control !optional;

   }

}

 

div.actions {

   input[type="submit"] {

      @extand .my-2 !optional;

      @extand .btn !optional;

      @extand .btn-primary !optional;

   }

}

上記はRailsで生成されたフォームはfieldとういタグで囲まれているので、そのタグに対して@extand .form-group; とすることでフォームのスペースを調整するbootstrapのクラスをあてている。

ただ、分からない点は多数あります、、まず

@extandとは…

 extandの機能を使うと、指定したセレクタのスタイルを継承できる

 

@importとは…

 cssの場合、import先のcssファイルを読み込む。

 sassの場合、importしたsassファイル内に展開されます。そして、一つのcssファイルになる。しかし、この場合scssファイルは存在する。。

 自分は以下のサイトを参考にしました。

http://kfug.jp/handson/try_sass/

 

そもそもSassとは

 Ruby製のcssメタ言語

 CSSの場合長く複雑になってしまう言語でも、分かりやすくシンプルに書けるのが特徴。またcssとの大きな違いは入れ子(ネスト構造)による記述が可能。

 

ScssとSass何が違うの?

 違いは書き方であり、一般的なのはscssだそうです。

 自分は以下のサイトを参考にしました。

scss・sass徹底入門。使い方や導入方法を説明【CSS】|ferret

 

 

deviseの削除ボタンにbootstrapのクラスを適用するため、

app/asetts/stylesheets/devise.scss を作成し、下記のように記述

input[type="submit"] [value="Cancel my account"] {

   @extand .btn !optional;

   @extand .btn-danger !optional;

}

 

 

またscssを読み込めるように app/asetts/stylesheets/application.scss

@import "forms";

@import "devise"; 

を追記

 

これで Rails s でサーバーを立ち上げ、確認してみます。

ところが、エラー文が…

f:id:fluid_27:20201016185647p:plain

The asset "application.js" is not present in the asset pipeline.

とあって、application.jsがないよ。って言ってる。

 

どういうこと?調べたところ、

Rails5まではsprocketsを利用したアセットパイプラインという仕組みでjavascriptcssを管理していたそうですが、Rails6からはWebpackerという仕組みで管理しているために Rails new をしてもapp/assets/javascripts/application.jsが作成されなかったのが原因だったようです。

 

app/view/layouts/home/html.erb の

javascript_include_tag

javascript_pack_tag

に直したら解決しました。

 

ここでいったん一区切り。

 

また、超絶駆け出しエンジニアなので、突っ込みどころがあればご指導・ご鞭撻いただけると幸いです。