Rails new~ ログイン機能まで

Rails new

ディレクトリ作成
rails newコマンドでアプリの雛形を作成
バージョンを指定しないとインストールされている最新のrailsのバージョンでアプリが作成される

$ rails _railsのバージョン_ new アプリケーション名

$ rails new Board_app -d

-dオプション

作成したアプリで使用するデータベースの種類を指定するオプション。
オプションを使わない場合はsqlite3というデータベースで作成される。

DBの作成

$ rails db:create

$rails db:migrate

ここでサーバー起動
$ rails s

流れ

  • rails newコマンドで新規railsアプリを作成

  • 作成されるGemfileを編集

  • bundle installコマンドを実行

  • rake db:createコマンドでデータベースを作成

  • routes.rbファイルにルーティングを定義

  • その他必要なファイルの作成 ...

トップページの作成

概要

  • layoutファイル
  • マニフェストファイル
  • パーシャル
  • ヘルパーメソッド
  • cssの種類
  • Railsにおける処理の全体像

    トップページの作成

  • routes.rbにてルーティングを設定

  • 全ページに共通して表示されるヘッダーとフッターを設定

    topのviewを作成

    top.html.erbをview/static_pages/配下に配置

    コントローラーの作成

    static_pages_controllerを作成し、topアクションを定義した上で、ルートパスにアクセスするとstatic_pages/top.html.erbテンプレートを使って画面がレンダリングされるように設定。
    $ rails g controller static_pages

  class StaticPagesController < ApplicationController
    def top; end
  end

controller名はモデルと結びつきがある場合は複数形にする。

ルーティング

Rails.application.routes.draw do
  root to: 'static_pages#top'
end

ヘッターとフッターの設定

views配下にsharedディレクトリを作成し、そこにheader.html.erb、footer.html.erbを配置
全ページからヘッダー(header.html.erb)、フッダー(footer.html.erb)が読み込まれるよう設定。

  <!DOCTYPE html>
<html>
  <head>
    <title>ffxiv</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 'shared/header' %>
    <%= yield %>
  <%= render 'shared/footer' %>
  </body>
</html>

application.html.erbから全ページで読み込まれるようにレンダーさせる。
titleを変えるとページタブ上のタイトルが変わる。

viewを成形

assets/images配下に画像sample.jpg, logo.png, top.jpgを配置
image_tagで配置した画像を読み込むようにパスを設定。

  <header>
  <nav class='navbar navbar-expand-lg navigation navbar-light bg-light'>
    <%= link_to root_path, class: 'navbar-brand' do %>
      <%= image_tag 'logo.png' %>
    <% end %>
    <button class='navbar-toggler' 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 ml-auto main-nav align-items-center'>
        <li class='nav-item dropdown dropdown-slide'>
          <a href='#' class='nav-link dropdown-toggle' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false'>
            掲示板
          </a>

          <div class='dropdown-menu dropdown-menu-right'>
            <%= link_to '掲示板一覧', '#', class: 'dropdown-item' %>
            <%= link_to '掲示板作成', '#', class: 'dropdown-item' %>
          </div>
        </li>

        <li class='nav-item'>
          <%= link_to 'ブックマーク一覧', '#', class: 'nav-link' %>
        </li>

        <li class='nav-item dropdown dropdown-slide'>
          <a href='#' class='nav-link' data-toggle='dropdown' aria-haspopup='true' aria-expanded='false' id='header-profile'>
            <%= image_tag 'sample', size: '40x40', class: 'rounded-circle mr15'%>
          </a>
          <div class="dropdown-menu dropdown-menu-right">
            <div class='dropdown-item'> meo <div>
            <div class='dropdown-divider'></div>
            <%= link_to 'プロフィール', '#', class: 'dropdown-item' %>
            <%= link_to 'ログアウト', '#', class: 'dropdown-item' %>
          </div>
        </li>
      </ul>
    </div>
  </nav>
</header>

CSSの設定

top.scssをassets/stylesheets/配下に配置。
application.cssapplication.scssにリネームし、application.scssからtop.scssを読み込むように設定する。

 @import 'top';

bootstrap導入

以下、bundle

gem 'bootstrap', '~> 4.4.1'
gem 'font-awesome-sass', '~> 5.12.0'
gem 'jquery-rails'

application.scssに以下の記載

 @import 'top';
 @import 'bootstrap'; 
 @import 'font-awesome-sprockets';
 @import 'font-awesome';

gem 'font-awesome-rails' では、font-awesome5系に対応していないので gem 'font-awesome-sass'を使用する必要がある。

 @import 'top';
 @import 'bootstrap'; 
 @import 'font-awesome-sprockets';
 @import 'font-awesome';

assets/javascripts/application.jsに以下の記載

//= require jquery3
//= require popper
//= require bootstrap-sprockets
//= require_tree .

//= require_tree . は一番下の行に記載していること

ログイン機能作成

gem 'sorcery' bundleする

ジェネレータを実行しrails db:migrateする。
userモデル、マイグレーションファイル、usersテーブルが作成される。

$ rails g sorcery:install
      create  config/initializers/sorcery.rb
      generate  model User --skip-migration
      invoke  active_record
      create    app/models/user.rb
      insert  app/models/user.rb
      create  db/migrate/20211027055241_sorcery_core.rb

データベースにlast_name、first_nameカラムをstring型で追加
rails g migration Addカラム名Toテーブル名 カラム名:カラムのデータ型

$ rails g migration AddLastNameToUsers last_name:string
$ rails g migration AddFirstNameToUsers first_name:string

$ rails db:migrate
== 20211027060856 AddLastNameToUsers: migrating ===============================
-- add_column(:users, :last_name, :string)
   -> 0.0011s
== 20211027060856 AddLastNameToUsers: migrated (0.0013s) ======================

== 20211027061037 AddFirstNameToUsers: migrating ==============================
-- add_column(:users, :first_name, :string)
   -> 0.0016s
== 20211027061037 AddFirstNameToUsers: migrated (0.0018s) =====================

Userモデルの作成

validationを定義

  class User < ApplicationRecord
  authenticates_with_sorcery!

  validates :password, length: { minimum: 3 }, if: -> { new_record? || changes[:crypted_password] }
  validates :password, confirmation: true, if: -> { new_record? || changes[:crypted_password] }
  validates :password_confirmation, presence: true, if: -> { new_record? || changes[:crypted_password] }

  validates :email, uniqueness: true
  validates :email, presence: true
  validates :first_name, presence: true, length: { maximum: 255 }
  validates :last_name, presence: true, length: { maximum: 255 }
end

ルーティング

ログイン、ログアウト、ユーザー新規作成を定義

Rails.application.routes.draw do
  root to: 'static_pages#top'
  get 'login', to: 'user_sessions#new'
  post 'login', to: 'user_sessions#create'
  delete 'logout', to: 'user_sessions#destroy'
  resources :users, only: %i[new create]
end

ユーザー新規登録画面の作成

usersコントローラの作成
bundle exec rails generate controller users
newメソッドとcreateメソッドを追加

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to login_path
    else
      render :new
    end
  end

  private

  def user_params
    params.require(:user).permit(:email, :password, :password_confirmation, :last_name, :first_name)
  end
end

新規登録画面のviewを作成

form_with

modelオプションを使う場合、form_withの引数には保存したいテーブルのクラスのインスタンスを指定。
usersテーブルに新たにレコードを追加したのでコントローラーに下記の記述をしている。

def new
 @user = User.new
end
# 新規に作成したレコードなのでcreateアクションが動く
この@user をform_withの引数に指定する。
コントローラーで作成したインスタンスがnewメソッドで新たに作成されて何も情報を持っていなければ自動的にcreateアクションへ、findメソッドなどで作成され、すでに情報を持っている場合はupdateアクションへ自動的に振り分ける
  <div class="container">
  <div class="row">
    <div class="col-md-10 offset-md-1 col-lg-8 offset-lg-2">
      <h1>ユーザー登録</h1>
      <%= form_with model: @user, local: true do |f| %>
        <div class="form-group">
          <%= f.label :last_name %>
          <%= f.text_field :last_name, class: 'form-control' %>
        </div>
        <div class="form-group">
          <%= f.label :first_name %>
          <%= f.text_field :first_name, class: 'form-control' %>
        </div>
        <div class="form-group">
          <%= f.label :email %>
          <%= f.email_field :email, class: 'form-control' %>
        </div>
        <div class="form-group">
          <%= f.label :password %>
          <%= f.password_field :password, class: 'form-control' %>
        </div>
        <div class="form-group">
          <%= f.label :password_confirmation %>
          <%= f.password_field :password_confirmation, class: 'form-control' %>
        </div>
        <%= f.submit '登録', class: 'btn btn-primary' %>
      <% end %>
      <div class='text-center'>
        <%= link_to 'ログインページへ', login_path %>
      </div>
    </div>
  </div>
</div>

ログイン画面の作成

$ bundle exec rails generate controller user_sessions
セッションコントローラーにnewメソッドとcreateメソッドを追加

  class UserSessionsController < ApplicationController
  def new; end
  
  def create
    @user = login(params[:email], params[:password])
    if @user
      redirect_back_or_to root_path
    else
      render :new
    end
  end
end

ログイン前のヘッダーを作成

  <header>
  <nav class="navbar navbar-expand-lg navigation navbar-light bg-light">

    <%= link_to root_path, class: 'navbar-brand' do %>
      <%= image_tag 'logo.png' %>
    <% end %>

    <button class='navbar-toggler' 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 ml-auto main-nav align-items-center">
        <li class="nav-item">
          <%= link_to 'ログイン', login_path ,class: 'nav-link' %>
        </li>
      </ul>
    </div>
  </nav>
</header>

ログイン状態によりヘッダーの表示が変わるように設定
logged_in?メソッドで現在のユーザーがログインしているかどうかを判別する。

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

    <%= stylesheet_link_tag    'application', media: 'all' %>
    <%= javascript_include_tag 'application' %>
  </head>

  <body>
  <% if logged_in? %>
    <%= render 'shared/header' %>
  <%else%>
    <%= render 'shared/before_login_header' %>
  <% end %>
  <%= yield %>
  <%= render 'shared/footer' %>
  </body>
</html>

ログアウト処理の追加

UserSessionControllerにログアウト処理のdestroyメソッドを追記

def destroy
    logout
    redirect_to root_path
end

ヘッダーのログアウトリンクのパスを追加
link_toメソッド
Railsでは主にviewファイルで使用され、引数を指定することでリンクを生成する。
<%= link_to 'リンクの文言', 'パス', class: 'クラス名', method: :HTTPリクエスト %>

<%= link_to 'ログアウト', logout_path, class: 'dropdown-item', method: :delete %>