railsアプリを作成 before_action

# 行うこと
・例外処理をする
・エラーメッセージを表示させる

# 例外処理を行う。
```users_controller.rb
.
.
.
  def login
    @user = User.find_by email: params[:email], password: params[:password]
    if @user
      flash[:notice] = "ログインに成功しました。"
      redirect_to "/users/#{@user.id}"
    else
      render "login_form"
    end
  end
.
.
.
def create
    @user = User.new(name: params[:name],email: params[:email],
                     password: params[:password])
    if @user.save
      flash[:notice] = "新規作成に成功しました。"
      redirect_to "/users/#{@user.id}"
    else
      render "users/new"
    end
  end
.
.
.
```

# エラーメッセージをつける
## コンソールで実験
```rb
irb(main):004:0> user = User.new(name: "saburou", email: "saburou@saburou")
=>
#<User:0x0000000113a11350
...

irb(main):005:0> user.save
  TRANSACTION (2.5ms)  BEGIN
  User Exists? (0.7ms)  SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'saburou@saburou' LIMIT 1
  User Exists? (0.4ms)  SELECT 1 AS one FROM `users` WHERE `users`.`password` IS NULL LIMIT 1
  TRANSACTION (0.3ms)  ROLLBACK
=> false

irb(main):006:0> user.errors.full_message
/Users/hyoudoumasatomo/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activemodel-7.0.2.3/lib/active_model/errors.rb:419:in `full_message': wrong number of arguments (given 0, expected 2) (ArgumentError)

irb(main):007:0> user.errors.full_messages
=> ["Password can't be blank"]
```
```rb
irb(main):009:0> user = User.new(name: "saburou")
=> #<User:0x0000000115a4baf8 id: nil, name: "saburou", email: nil, passwo...

irb(main):010:0> user.errors.full_messages
=> []

irb(main):011:0> user.save
  TRANSACTION (0.3ms)  BEGIN
  User Exists? (0.4ms)  SELECT 1 AS one FROM `users` WHERE `users`.`email` IS NULL LIMIT 1
  User Exists? (0.4ms)  SELECT 1 AS one FROM `users` WHERE `users`.`password` IS NULL LIMIT 1
  TRANSACTION (0.3ms)  ROLLBACK
=> false

irb(main):012:0> user.errors.full_messages
=> ["Email can't be blank", "Password can't be blank"]
```
なるほど```errors.full_messages```は配列なのか。
これでブロック構文を使っている意味がわかった。
これでどう表示されるかがわかった。

# ログイン中にする。
session[:user_id] = user.idを使いログイン中にする。

#　他のユーザーの詳細ページで編集できないようにする
条件をつける
そのためにアクションが起こる前に```before_action```を作動させる。
自分と他のユーザーが違うことを表せばいい
なんだかわからなくなった。
リンクを表示させない。
カレントユーザーでなんとかならないか？

編集のリンクを表示させない。
コントローラのアクションを作動させない。
この２つで完了と考えている。
コントローラの作動が考えてみよう。
# ログイン中のユーザーしかコントローラー作動させない。
アクションを作動させる前に```before_action```があったはずだ。
これを使うとアクションが作動しなくなるからだ。
```application_controller```でメソッドを作成し、それをもとに判断させる。
```@current_user```のインスタンス変数を作成、それでfalseだった場合はアクションを作動させない。
じゃあどういう風にfalseになるか？
それはsession[:user_id]になかったらだろう。

```application_controller.rb
  def set_current_user
    @current_user = User.find_by(id: session[:user_id])
  end
```
before_actionをつけていないからか？
progateのテキストに各コントローラがアクションを作動させる前に```before_action```が作動しない。
```application_controller.rb
class ApplicationController < ActionController::Base
  before_action :set_current_user

  def set_current_user
    @current_user = User.find_by(id: session[:user_id])
  end
end
```
```application_controller.rb```に書いておくことで各アクションが作動させる前にインスタンス変数を定義することができる。
## 思ったこと
なるほどこういうことか
制限するアクションのコントローラーにメソッドを定義するそして```before_aciton```を作動させる。

表示させる。
```application_controller.rb
.
.
.
       <% if @current_user %>
         <li>
           <%= @current_user.id %>
         </li>
       <% end %>
.
.
.
```
これを書いた。成功！
何回も言うが```before_action```で準備をしなければ定義していても作動はしない。

## editアクションにbefore_actionを備え付ける。
と思った。
が書こうとしたら違うと思った。
メソッドの内容はcurrent_userのidとそれ以外のidの見分けをつけることが大事だからだ。
```users_controller.rb
  before_action :check_user, only: [:edit]
.
.
.
  def check_user
    if @current_user.id != params[:id]
      flash[:notice] = "権限がありません"
      redirect_to "/"
    end
  end
```
編集リンクを押したときは:idのパラメータしかないので
こうすると違うことがわかるのでこれでできた。
成功！

今日はこの辺で。