管理画面へのログイン機能、管理画面トップページの作成 { 続き

前回の続き、

 

ヘルパーで編集が完了したら、今度は表示させる部分にももう一工夫必要だ。

admin/layouts/application.rb

<title><%= page_title(yield(:title), admin: true) %></title>

admin: true というのを付け加える事で管理者の時のページタイトルとそうでない一般時の表示を変えるために必要である。

なのでページタイトルが必要なビューの上部には

<% content_for(:title, t('.title')) %>  #titleは翻訳ファイルに記入

を記入すればよい(多分既に今までやっているはず…)

翻訳 ja.ymlファイル


config/locales/views/ja.yml

...
...
not_updated: "%{item}を更新できませんでした"
       deleted: "%{item}を削除しました"
       delete_confirm: '削除しますか?'
       not_authorized: '権限がありません'  # ← ここを追加
   users:
     new:
       title: 'ユーザー登録'
     update:
       success: 'パスワードを変更しました'
       fail: 'パスワードの変更に失敗しました'
 
   admin:                          # ここから追加 ↓ ---
     user_sessions:
       new:
         title: 'ログイン'
       create:
         success: 'ログインしました'
         fail: 'ログインに失敗しました'
       destroy:
         success: 'ログアウトしました'
     dashboards:
       index:
         title: 'ダッシュボード'       # --- ここまで追加 ---

マニフェストファイル


app/assets/application.cssまたは.jsのファイルのこと

Rails 6 でプロダクト開発を学ぼう - Railsチュートリアル

 

アセットパイプライン

アセットパイプライン - Railsガイド

 

[書籍]現場で使えるRuby on Rails 内にあったものの方がイメージが湧きやすいと思う

f:id:michimo_10:20210607132005j:plain

現場Rails



今まではapplication.jsやscssを読み込んでいたが、管理者のページは見た目が異なるため別々に管理していきます。その方が後々管理が楽だから。

今までの app/assets/javascripts/application.js

 //= require jquery3
 //= require popper
 //= require bootstrap-sprockets
 //= require rails-ujs
 //= require activestorage
 //= require_tree .

今回の app/assets/javascripts/application.js

//= require jquery3
 //= require popper
 //= require bootstrap-sprockets
 //= require rails-ujs
 //= require activestorage
 //= require admin-lte/dist/js/adminlte.min

//= require_tree . これを削除した。なぜかというと

//= require tree.でapplication.js配下の全ファイルを読み込んでいました。 しかしこのままではadminのファイルと同じように一般でも読み込まれてしまうので、別途admin.jsとscssファイルを作成します。(ファイルの場所は同じフォルダで良い)

app/assets/javascripts/admin.js

//= require jquery3
//= require rails-ujs
//= require admin-lte/plugins/bootstrap/js/bootstrap.bundle.min
//= require admin-lte/dist/js/adminlte

app/assets/javascripts/admin.scss

@import "font-awesome-sprockets";
@import "font-awesome";
@import 'admin-lte/plugins/fontawesome-free/css/all.min.css';
@import 'admin-lte/dist/css/adminlte.min.css';

・assets アセットの設定


今回作成したレイアウトやビューも綺麗に読み込ませるためのcss[scss]やjsも必要である。

まず、config/initializers/assets.rbのファイルの中でコメントアウトになっている

# Rails.application.config.assets.precompile += %w( admin.js admin.css )

という文を探す。

そしたらコメントアウトを外し、利用できるようにしておく

Rails.application.config.assets.precompile += %w[admin.js admin.css]

この際、()を[]に変更する。これで、admin.js admin.cssをプリコンパイルします

他のマニフェストや、個別のスタイルシート/JavaScriptファイルをインクルードしたい場合は、config/initializers/assets.rbのprecompileという配列を使用します。 (Railsガイド)

管理者の登録


管理者の登録もしておかなければならないので

$ rails c でUser.all またはUser.find(1)などで権限を与えたいuserを探す

探せたらuser = User.find()でuserに情報を渡す

user.admin = true

#エラがー出たら!か?の表記があるのでuser.admin! = trueで破壊的(?)に権限を与えてやる User.admin で 先ほど登録したuserが管理者権限を持っているのでログインで使うことができる

[初心者]Railsで管理者権限付与してみた - Qiita

ログインして検証ツールを開きレイアウトなど確認して崩れがなけばよし

回答にあったjsonの記載

ディレクトの下〜〜の方にあるpackage.jsonファイルの中で

{
   "name": "runteq_normal",
   "private": true,
   "dependencies": {  #ここから
     "admin-lte": "^3.0.0-rc.6"
   }   # ここまで
 }

#の部分を追記していた

パスワードリセット

ActionMailerを使う

letter_openerというgemを使う

トークンにユニーク制約をする

ログイン画面にリセットページのリンク作成

開発環境では送れないようにする

リセット画面の作成

クリックすると反応するメールのフォームとラベルをつける

リセットの申請をするとログインページに戻る

OKでもNGでも送信完了のフラッシュが出る

Sorcery/sorcery

githubに手順が書いてある

もしくはこれ

【Rails】パスワード変更(トークンがどのように使用されているのか) - Qiita

mailerはこれ

Action Mailer の基礎 - Railsガイド

・migrationのエラー


$ rails g sorcery:install reset_password --only-submodules

sorceryの機能を使うため上を入力。

Addでマイグレーションを自動追加になるがdb:migrate出来ない現象に陥った。理由はテーブル名の違い。 sorceyの機能で作成したカラムではUserと出ていたが、実際今まで作っていたのはusersというテーブル名だったのでAddのマイグレーションファイル内のテーブル名をUserからusersに変える必要があった。

上記のsorceryのコマンドで生成されたsorcery.rbの中に[:reset_password]というのが7行目あたりに記載されているはずだ、もしなければ[]内に記載する。

また、その下にあるRails.application.config.sorcery.configure do |config| ももし無ければ記載する

# The first thing you need to configure is which modules you need in your app.
# The default is nothing which will include only core features (password encryption, login/logout).
#
# Available submodules are: :user_activation, :http_basic_auth, :remember_me,
# :reset_password, :session_timeout, :brute_force_protection, :activity_logging,
# :magic_login, :external
Rails.application.config.sorcery.submodules = [:reset_password]  # ← ここ

# Here you can configure each submodule's features.
Rails.application.config.sorcery.configure do |config|
  # -- core --
  # What controller action to call for non-authenticated users. You can also

ここでの注意は下にコメントアウトされている中で既に記載があるものは重複して書かないようにすること。必要なものはコメントアウトを外して利用する。

なので今回必要なのは

244行目あたりの config.user_config do |user|

394行目あたりの # user.reset_password_mailer = の部分にUserMailerを付け足す

395行目あたりに end

554と555行目あたりのconfig.user_class = 'User' と end である

まとめると以下の表示だが、qiitaやgithubにはそこまで書かれていないため コメントアウトインデントに気をつけて利用する

Rails.application.config.sorcery.submodules = [:reset_password]

Rails.application.config.sorcery.configure do |config|
  config.user_config do |user|
    user.reset_password_mailer = UserMailer
  end
	config.user_class = 'User'
end

・mailerの作成


$ rails g mailer UserMailer reset_password_email

上記をすることでapp/mailersファイルが生成される

viewsの中にもtextとhtml用のファイルがあり、中には届くメール内容を記述する

app/views/user_mailer/reset_password_email.text

<%= @user.decorate.full_name %>様
パスワード再発行のご依頼を受け付けました。
こちらのリンクからパスワードの再発行を行ってください。
<%= @url %>

app/views/user_mailer/reset_password_email.html.erb

<%= @user.decorate.full_name %>様
<p>パスワード再発行のご依頼を受け付けました。
こちらのリンクからパスワードの再発行を行ってください。</p>

<p><a href="<%= @url %>"><%= @url %></a></p>

上記の@urlにはtokenが発行された再登録用のurlが入る

app/mailers/user_mailer.rb

class UserMailer < ApplicationMailer
	def reset_password_email(user)
	    @user = User.find(user.id)
	    @url = edit_password_reset_url(@user.reset_password_token)
	    mail(to: user.email,
	         subject: 'パスワードリセット')
  end
end

・コントローラーの作成


$ bundle exec rails g controller PasswordResets new create edit update

中身を書いていく

class PasswordResetsController < ApplicationController
  skip_before_action :require_login
  # ログインする前にパスワード変更のページで使いたいので上記が必要
  def new; end

  def create #パスワードリセット対象のメールアドレスを申請して、リセットの対象を作成する
    @user = User.find_by(email: params[:email]) #メールアドレスの登録があれば@userに渡す
    @user&.deliver_reset_password_instructions!
    redirect_to login_path, success: t('.success')
  end

  def edit #パスワードリセット用のメールのURLをクリックして、新しいパスワードを入力する。
    @token = params[:id]
    @user = User.load_from_reset_password_token(@token)
    return not_authenticated if @user.blank?
  end

  def update #パスワードリセット(edit)ページにて、『更新する』ボタンでパスワードを変更する。
    @token = params[:id]
    @user = User.load_from_reset_password_token(@token)
    return not_authenticated if @user.blank?

    @user.password_confirmation = params[:user][:password_confirmation]
    if @user.change_password(params[:user][:password])
			 redirect_to login_path, success: t('.success')
    else
      flash.now[:danger] = t('.fail')
      render :edit
    end
  end
end

コントローラー内で出てきたメソッドの意味(github内で検索)


**deliver_reset_password_instructions** メソッド

# Generates a reset code with expiration and sends an email to the user.
	# 期限付きのリセットコードを生成し、ユーザーにメールを送信します。
          def deliver_reset_password_instructions!
            mail = false
            config = sorcery_config
            # hammering protection # ハンマーによる保護
            return false if config.reset_password_time_between_emails.present? && send(config.reset_password_email_sent_at_attribute_name) && send(config.reset_password_email_sent_at_attribute_name) > config.reset_password_time_between_emails.seconds.ago.utc

**load_from_reset_password_token** メソッド

module ClassMethods
          # Find user by token, also checks for expiration.
						# トークンでユーザーを見つけ、有効期限もチェックします。
          # Returns the user if token found and is valid.
						# トークンが見つかり、有効であればユーザーを返します。
          def load_from_reset_password_token(token, &block)
            load_from_token(
              token,
              @sorcery_config.reset_password_token_attribute_name,
              @sorcery_config.reset_password_token_expires_at_attribute_name,
              &block
            )
          end

**change_password** メソッド

# Clears token and tries to update the new password for the user.
	# トークンをクリアして、ユーザーの新しいパスワードの更新を試みます。
          def change_password(new_password, raise_on_failure: false)
            clear_reset_password_token
            send(:"#{sorcery_config.password_attribute_name}=", new_password)
            sorcery_adapter.save raise_on_failure: raise_on_failure
          end

・メール送信の確認、環境変数の設定


Gemfileにletter_openerとconfigを追加する

  gem 'config' #このgemが環境変数を変更するのでグループの指定はせず外に書く

group :development, :test do  #開発環境とテスト環境で使えるようにするため,このgroupに記入
	gem 'letter_opener_web', '~> 1.0'
end
 $ bundle install

config

ホスト情報は開発環境、ステージング環境、本番環境で異なる


configのgemを入れると環境にまつわるlocalやdevelopmentなど…のファイル生成される。

さまざまな環境に柔軟に対応するために今回は config/settings/development.yml に

 host = Setting.host 

とするとすっきりするだけでなく、管理する箇所が環境のファイル1箇所にまとまるので保守性も非常に高まる。

letter_opener

開発環境などで送信したメールを確認するため


・ルーティングの編集


コントローラーを追加したので遷移先を指定する。

それと同時にメールが届いたかを判断するためにletter_openerを使用するために以下も追加する

resources :password_resets, only: %i[new create edit update]
mount LetterOpenerWeb::Engine, at: '/letter_opener' if Rails.env.development?
	# ↑ 'localhost:3000/letter_opener'で開くことができる

Userモデル

allow_nil: trueを追加

パスワードを変更した際、reset_password_tokenがnilになるのでユニーク制約に引っかかってしまう。そこで、allow_nil:trueを加えることでnilを許可しておく。

validates :reset_password_token, uniqueness: true, allow_nil: true

config/environments/test.rb

config.action_mailer.default_url_options = { host: 'localhost:3000' }

config/environments/development.rb

config.action_mailer.perform_caching = false # 36行目あたりコメントアウト

config.action_mailer.default_url_options = { host: Settings.host }
 # 一番下部分をコメントアウトし {}内を編集

config.action_mailer.delivery_method = :letter_opener_web # ← 追加

・ビュー


ここまで出来たらコントローラー作成時にできたviewファイルに、送信フォームのhtmlを書いていく

:password変更のメールを送信するページ app/views/password_resets/new.html.erb

<% content_for(:title, t('.title')) %>
 <div class="container">
   <div class="row">
     <div class="col-md-10 offset-md-1 col-lg-8 offset-lg-2">
       <h1><%= t('.title') %></h1>
       <%= form_with url: password_resets_path, local: true do |f| %>
         <div class="form-group">
           <%= f.label :email, t(User.human_attribute_name(:email)) %><br />
           <%= f.email_field :email, class: 'form-control' %>
         </div>
         <%= f.submit t('password_resets.new.submit'), class: 'btn btn-primary' %>
     <% end %>
     </div>
   </div>
 </div>

:メール送信後にpasswordを再設定するページ app/views/password_resets/edit.html.erb

<% content_for(:title, t('.title')) %>
 <div class="container">
   <div class="row">
     <div class="col col-md-10 offset-md-1 col-lg-8 offset-lg-2">
       <h1><%= t('.title') %></h1>
       <%= form_with model: @user, url: password_reset_path(@token), local: true do |f| %>
         <%= render 'shared/error_messages', object: f.object %>
 
         <div class="form-group">
           <%= f.label :email %>
           <%= @user.email %>
         </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>
         <div class="actions">
           <p class="text-center">
             <%= f.submit class: 'btn btn-primary' %>
           </p>
         </div>
       <% end %>
     </div>
   </div>
 </div>

:ログイン画面下にリンクを表示させる app/views/user_sessions/new.html.erb

<% end %>
       <div class='text-center'>
         <%= link_to (t '.to_register_page'), new_user_path %>
         <%= link_to (t '.password_forget'), new_password_reset_path %>
       </div>                     # ↑ この部分
     </div>
   </div>

【Rails】画面下の番号をクリックすると次のページにいくやつ【ページネーション】

備忘録:
こういうやつ↓これを一覧表示するページの下に表示させる

f:id:michimo_10:20210414181641p:plain
pagenate


gemを入れる

今回使うのはRailsのkaminariというgem。

github.com

そして、やり方

qiita.com

基本的に上のようにやっていけば良し
Gemfile内にgem 'kaminari'を記述してから
ターミナルで$ bundle installする

コントローラーに直接ページ数を書かないようにするべく別ファイルを用意する。
$ rails g kaminari:config
↑をターミナルで実行し、

生成されたファイルの中から必要な部分のコメントを外したり数字を変更する

kaminariのファイル

config/initializers/kaminari_config.rb

# frozen_string_literal: true

Kaminari.configure do |config|
  config.default_per_page = 20  
  # ↑のコメントアウトを外し、数を変更し1ページに何項目表示するか設定する、それ以外は自由に変更する
  # config.max_per_page = nil
  # config.window = 4
  # config.outer_window = 0    #  ←【1】
  config.left = 2  #  ← 【2】
  config.right = 2 #  ←  【3】
  # config.page_method_name = :page
  # config.param_name = :page
  # config.max_pages = nil
  # config.params_on_first_page = false
end

【1】

f:id:michimo_10:20210414225811p:plain
pagenate
両端の2つ前である[1][2]と次の[60][61]の番号表示される

【2】
左側に2つ番号を表示させる[1][2]の部分
【3】
右側に2つ番号を表示させる[60][61]の部分

コントローラー部分

一覧表示する部分(index,bookmarks)のアクションにkaminariのメソッドのpage(params[:page])を付け足してあげる
boards_controller

class BoardsController < ApplicationController
  before_action :set_params, only: %i[edit update destroy]
  def index
    @boards = Board.all.includes(%i[user bookmarks]).order(created_at: :desc).page(params[:page])
  end

#省略

  def bookmarks
    # bookmarksメソッドの定義
    @bookmark_boards = current_user.bookmark_boards.includes(:user).order(created_at: :desc).page(params[:page])
    # @bookmarksに(=) ログインしているユーザーの,掲示板たちが,userモデルに含まれていたら,作成日が新しい順に並べる.ページ下にべネーションを使い表示を小分けにする



ビュー部分


views/boards/index.html.erb

   <!-- 掲示板一覧 -->
  <div class="row">
    <div class="col-12">
      <div class="row">
        <% if @boards.present? %>
          <%= render @boards %>
        <% else %>
          <p><%= t('.fail') %></p>
        <% end %>
      </div>
      <%= paginate @boards %> # この部分を追加,コントローラーのindexに記した@boardsによってデータを一覧が表示される
    </div>
  </div>
</div>

views/boards/bookmarks.html.erb

   <!-- お気に入り掲示板一覧 -->
  <div class="row">
    <div class="col-12">
      <div class="row">
        <% if @bookmark_boards.present? %> # もし,お気に入りの掲示板が無かったら
          <%= render @bookmark_boards %>
          #renderの闇 partialは_board.html.erbを呼び出し, collection:で@bookmarks_boards(お気に入りの掲示板)を繰り返し表示する要素 
          # partial: と collection: で1セット! じゃないとエラーになる 
        <% else %>
          <p><%= t('bookmarks.fail') %></p>
 # locales/activerecord/ja.yml内に記載したboard内の翻訳で.failの部分の'掲示板がありません'を表示
        <% end %>
      </div>
    </div>
    <%= paginate @bookmark_boards %>
    #  ↑ この部分を追加
  </div>
</div>

【パソコン】Rails初学者の覚えること

初学者向けであり備忘録


Spotlight検索
- ターミナルやブラウザなど検索してすぐ表示させる
[⌘command] + スペースキー

Railsでクセづけること

Railsで使えるメソッドの機能を知ること(なるべく覚えると後々ラクになる)

Gemfileいじったら(添削などの変更)
$ bundle install
もしくは$ bundle

モデルやルーティング、コントローラーのファイルを添削などを変更し
ブラウザで反映を確認する時はサーバーを再起動させる $ rails s

モデル(model)を作る時は単数形

コントローラー(controller)を作る時は複数形

ターミナル編

現在の設定の確認
$ echo $SHELL

変更可能なシェルの確認(一覧で表示される)
$ cat /etc/shells

使用するターミナルのシェルを変更する ( chshは change shell の略 )
$ chsh -s /bin/○○○

サーバーの立ち上げ
$ rails s

サーバーの終了
[^controlボタン] + c

コンソールの立ち上げ
$ rails c

コンソールの終了
[^controlボタン] + d
もしくは exitを入力

行の最初の文字へ
[^controlボタン] + a

行の最後の文字へ
[^controlボタン] + e

画面のログを綺麗にする(リセット)
[^controlボタン + l]
もしくはclearを入力

入力履歴表示


さらに詳しくはこちら
Macのターミナルコマンド一覧(基本編) - Qiita

普段から使えるショートカット


コピー
[⌘command] + c

切り取り
[⌘command] + x

ペースト(貼り付け)
[⌘command] + v

1個前に戻る(入力など)
[⌘command] + z

取り消し
[⌘command] + [↑shift] + z

部分選択(入力時など)
[↑shift] + 方向キー

タブを1個閉じる
[⌘command] + w

ウィンドウ(アプリ)を終了する
[⌘command] + q

スクリーンショット
画面全部
[⌘command] + [↑shift] + 3
範囲選択
[⌘command] + [↑shift] + 4 (マウスでドラッグする)

rails g コマンドで生成ファイルの制限

よくRailsでアプリを作るときにサンプルとして挙げられる
scaffold
これを使わずして作っていこうとしているのが
Railsチュートリアル railstutorial.jp

とはいえscaffold便利だよね~
正直よく分かってなくてもできあがっちゃうからscaffold無しで作れとなると鬼むずい


というわけでコマンドの使い方として
$ rails gをした時に特定のファイルが生成されない様にしてみる
手順はこちらにあります

qiita.com


まずはアプリの土台(scaffoldじゃない)となる部分をnewで作成しましょう
バージョンは
Ruby 2.6.4
Rails 5.2.3
Node.js v12.14.0 以降
Yarn 1.19.2 以降
です

$ rails new アプリケーション名



今回はsampleで作ってみたいと思います
$ rails new sample
$ rails s
localhost:3000に繋いでRailsの画面が表示されればOKです。
これでまっさらな状態のsampleアプリができました。

今回はassets、helper、testファイル、ルーティングが生成されないようにしてみましょう。

上のqiitaの記事もですが、大まかな流れはRailsガイドにも載っているので参考にしてください。

Rails ジェネレータとテンプレート入門 - Railsガイド



アプリ全体の設定に当たるのでconfig/application.rbを開きましょう
上のqiitaの記事をもとに以下を記入します。
config/application.rb

     # Don't generate system test files.
      config.generators.system_tests = nil

   config.generators do |g|  # ジェネレーターズ
      g.assets false  # assetsフォルダにはCSS, JavaScriptファイル生成しない
      g.skip_routes true # ルーティングを生成しない,trueならroutes.rb変更せず、falseなら通常通り変更
      g.test_framework false # testファイル生成しない
      g.helper false  #helperを生成しない
    end                    

これでcontrollerを作成するとターミナルで作成されるファイルの数が減っているのが分かります。
もし、間違ってしまった場合はrails destroyを使うことでrails gで作成したファイルやディレクトリを一気に削除してくれます。
例:$ rails destroy controller コントローラー名


---↓は後でもいいです---
それとは別で、今後使用するRSpecというものをgemファイルに追加しておきます
以下の記事を参考にしてください

RSpecを導入する - Qiita

Railsの処理の流れ

基本

Railsチュートリアルや書籍などでよく言われる
MVC
(モデル・コントローラー・ビュー)

実際の処理の流れは

CMV
コントローラ → モデル → ビュー

これが基本になるが、細かく言えばコントローラーに行く前にルーティングという処理も通る

なので、正確には
ルーティング → コントローラ → モデル → ビュー となる

ルーティング(routes.rb)で何をする?


ルーティングではURL(http://ほにゃらら/うんたら/)の部分で
http://ほにゃららにアクセスが来たら、
「コントローラー(○○_controller.rbファイル)の[うんたら]の処理をしてくださいね」というように、アクセスされたURLによって振り分けしてくれる部分

Rails.application.routes.draw do
  root 'static_pages#top'

  get 'login', to: 'user_sessions#new'
  post 'login', to: 'user_sessions#create'
  delete 'logout', to: 'user_sessions#destroy'
end


翻訳↓

Rails.application.routes.draw do
# rootはサイトのTOPページの部分であり / と書かれる
  root 'static_pages#top' 
 # ↑ http://localhost:3000/ にアクセスされた時、static_pages_controller.rbファイルのtopアクション(def top)に行く
  get 'login', to: 'user_sessions#new'
# ↑ http://localhost:3000/login にアクセスされた時、user_sessions_controller.rbファイルのnewアクション(def new)に行く
  post 'login', to: 'user_sessions#create'
# ↑ http://localhost:3000/login から何かしら入力したデータを送信した時、user_sessions_controller.rbファイルのcreateアクション(def create)に行く
  delete 'logout', to: 'user_sessions#destroy'
# ↑ http://localhost:3000/logout にアクセスされた時、user_sessions_controller.rbファイルのdestroyアクション(def destroy)に行く
end



コントローラーで何をする?

ターミナルでコントローラーを作成するときは複数形
コントローラー(〇〇_controller.rb)では上のルーティングで振り分けられた処理をします。ちょっとややこしいですが
controllers/user_sessions_controller.rb

class UserSessionsController < ApplicationController
  
  def new; end

  def create
    @user = login(params[:email], params[:password])
    if @user
      redirect_back_or_to boards_path, success: t('.success')
    else
      flash.now[:danger] = t('.fail')
      render :new
    end
  end

  def show
    @user = User.find(params[:id])
  end

  def edit; end

  def destroy
    logout
    redirect_to root_path, success: t('.success')
  end
end


翻訳↓ controllers/user_sessions_controller.rb

class UserSessionsController < ApplicationController

  def new; end
  # ↑ルーティングで振られたnewアクションだが特に処理は書いていないのでviewフォルダの中にあるuser_sessionsの(new.html.erbというファイル)を表示する

# ↓ルーティングで振られたcreateアクションの中
  def create # 作成(create)アクション
    @user = login(params[:email], params[:password])
# @userという変数に(=)、emailとpasswordのパラメーター(入力された値)を持ったloginを代入している
    if @user # もし@user(↑の値のデータをもつlogin)ならば
      redirect_back_or_to boards_path, success: t('.success') 
# boardsという別の処理にリダイレクトし,サクセス(成功)ということで"ログインしました"が画面に表示される❶
    else # もしくは
      flash.now[:danger] = t('.fail') 
      render :new
# newアクション(↑のdef new)のページにレンダリング(元になる情報を形成)してnew.html.erbに戻され、デンジャー(危険)で"ログインできませんでした"が表示される
    end
  end
#❶ success: t('.success')のsccess:はフラッシュといって画面に一時的に表示してくれる(ずっと表示もできる)機能でt('.success')はconfigフォルダ内に新たに作成したja.yml内に'ログインしました'を定義している(ja.ymlが適用されるにはgemfileに'rails-i18n'というgem(ジェム)と呼ばれる機能を追加してあげないといけない )

  def show # ルーティングでshowに振られたshowアクションの中
    @user = User.find(params[:id])
# [1]   @userには(=)Userクラス(User)のモデルに紐づいたidカラムにあるパラメーター(params[:id])を一つ取り出す(find)
  end

  def edit; end
# ルーティングでeditに振られたeditアクションの中はないのでnewと同様にedit.html.erbなどのviewを表示する

  def destroy #ルーティングでdestroyに振られたdestroyアクションの中
    logout # ログアウトしたら
    redirect_to root_path, success: t('.success') 
# ルートパス(/ のページ)にリダイレクトし、サクセス(成功)ということで'ログアウトしました'が表示される
  end
end

# * success: (サクセス)やdanger: (デンジャー)はbootstrapなどを入れることでcssやscssによって緑色や赤色で表示される
# ただsuccess:を入れれば言い訳ではなく、フラッシュメッセージを表示するviewの部分も作らないといけない



モデルで何をする?

モデルを作成するときは単数形
モデルはコントローラーとデータベースのやりとりをする場所
データベースに保存したり、データを引っ張ってきたりする
models/user.rb

class User < ApplicationRecord
end



ちなみにコントローラーで出た

@user = User.find(params[:id])

このUserという大文字の部分、

models/user.rb

class User < ApplicationRecord
#     ↑ この部分と同じ意味
end

つまり、なぜ大文字なのかというとUserモデルにアクセスしているので、
上の翻訳したコントローラー内の[1]に当たるわけである


また何でもかんでもデータベースに保存されては困るので、
例えば、以下の様に「空のまま送信できないようにする」とか、「文字数制限をつける」とかvalidate(検証)を決めることができる。

class User < ApplicationRecord
#      ↑ ユーザーの
  validates :first_name, presence: true, length: { maximum: 255 }
# ↑検証します 名字が空欄はダメで最大255文字まで
  validates :last_name, presence: true, length: { maximum: 255 }
# ↑検証します 名前が空欄はダメで最大255文字まで
  validates :email, presence: true, uniqueness: true
# ↑検証します メールアドレスが空欄はダメで値が重複していないこと
end



今回の場合、user_sessionsコントローラーでuserモデルのデータを引き出している

プログラミング初学者におけるclassという謎の部分

classは概念

class Abc

「このclassってなんや?」と思うんですが
色々と説明してくれてる記事があります
ただどうしても落とし所がわからない!という方もいると思いますので、
とりあえず「最初のうちはclassはclassというふうに覚えるしかない」としか言いようがなくて


「[あ]という字はなんで[あ]なの?」というくらい説明に困るものだと思います。

なので、「そういうもんだから!細えことは後々分かるから今はそういうものだと思え」

という感じです。

翻訳してみる

例えば学習してるとそのうち出てくる

class Abc

  def hello
    post = Abc.new 
  end
end

↑これとか頭が ??? になるのも分かります

自分なりに翻訳してみると

class Abc # Abcというクラス(class)があって

  def hello  # helloというメソッドを作ります
    post = Abc.new 
# postという変数に(=) Abcクラス(class)のnew(インスタンス{実体化したもの}を作成)を代入している
  end  # メソッドの定義はここまでです
end  #Abcクラスの定義はここまでです

という感じになります。

class?メソッド?インスタンス




はぁ?


お気持ちは分かります。私も未だにそうです。

説明は難しい

概念なので伝えることが難しく、classについては色々な方が記事を書いていますので探してみてください。 そのうちなんとなく「多分こういうもの」というのがわかってくると思います。




犬を見れば犬と分かるし、
ネコを見ればネコと分かるし、
う●こを見ればう●こと分かるし、



逆に、

なんでこれは犬なの?
なんでこれはネコなの?
なんでこれはう●こなの?
と聞かれると困ってしまうように

「生物学的に犬というものは〜云々カンヌン」
とか、そういったものを求めているのではなく


犬は犬だから犬

で通じますよね?

[犬は毛があって顔の形は…]

それじゃあネコとの違いは???

というパラドックスに陥ってしまうようなものなので、
「classはclass」という風に覚えてもらったほうがいいと思います。