rails5 progate 整理メモ　

# パスワードカラムを追加
```
rails g migration add_password_to_users
```
```
rails generate migration user image_name:string
```
違いは何だろう?
## カラムのデータ型を指定
```rb
class AddPasswordToUsers < ActiveRecord::Migration[5.0]
  def change
    add_column :users, :password, :string
  end
end
```

## １番目のユーザーのパスワードを変える
```rb
tweet_app $ rails console
Loading development environment (Rails 5.0.3)
[1] pry(main)> user = User.first
  User Load (0.1ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User:0x0000555f56c6f010
 id: 1,
 name: "あ",
 email: "hogehoge",
 created_at: Wed, 11 May 2022 14:53:09 JST +09:00,
 updated_at: Wed, 11 May 2022 16:36:05 JST +09:00,
 image_name: "1.jpg",
 password: nil>

[2] pry(main)> user.password = hogehoge
NameError: undefined local variable or method `hogehoge' for main:Object
from (pry):2:in `__pry__'

[3] pry(main)> user.password = "hogehoge"
=> "hogehoge"

[4] pry(main)> user.save
   (0.1ms)  begin transaction
  User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE "users"."email" = ? AND ("users"."id" != ?) LIMIT ?  [["email", "hogehoge"], ["id", 1], ["LIMIT", 1]]
  SQL (1.4ms)  UPDATE "users" SET "updated_at" = ?, "password" = ? WHERE "users"."id" = ?  [["updated_at", "2022-05-12 05:03:07.402656"], ["password", "hogehoge"], ["id", 1]]
   (12.6ms)  commit transaction
=> true
```
## パスワード属性にバリデーションをかける
```rb
class User < ApplicationRecord
  .
  .
  .
  validates :password, {presence: true}
end
```
# ログインフォームを作成する
まず```localhost:3000/login```にアクセス
```
Routing Error
No route matches [GET] "/login"
```
## ルーティングを設定
```routes.rb
Rails.application.routes.draw do
  get "/login" => "users#login"
.
.
.
end
```
## 行き先のコントローラに```login```アクションを設定する
```users_controller.rb
class UsersController < ApplicationController
.
.
.
  def login
  end
end
```
## 自動的にアクション名のファイルを探すのでファイルを作成する
```login.html.erb
内容を貼り付け
```
これで表示成功！

## ヘッダーに```ログイン```を表示させる
application.html.erbにリンクを書く。
```application.html
<li>
  <%= link_to("ログイン", "/login") %>
</li>
```

# ログイン処理を追加
フォームから送信されたメールアドレスとパスワードからユーザーを特定し、ユーザーが存在すればそのユーザーの情報をブラウザに保存するようにしましょう。

## まずボタンで送信できるようにしよう。

```login.html
    <%= form_tag("/login") do %>
      <div class="form users-form">
        <div class="form-body">
          <p>メールアドレス</p>
          <input>
          <p>パスワード</p>
          <input type="password">
          <input type="submit" value="ログイン">
        </div>
      </div>
    <% end %>
```
```<%= %>```をつけなければ中身が表示されない
## これで送信してみよう。
```
Routing Error
No route matches [POST] "/login"
```
ルーティングが設定されていなかった。
```routes.rb
Rails.application.routes.draw do
  get "/login" => "users#login"
  post "/login" => "users#login"
.
.
.
end
```
確か```form_tag```は基本的に```POST```のHTTPメソッドを使うはず...
だがらgetのルーティングには行かないと思う。

送信ボタンを押したがloginのページに行ってしまう。　  どういうことだろうか？

##　loginアクションを書いてみる
```user_controller.rb
class UsersController < ApplicationController
.
.
.
  def login
    @user = User.find_by(
      email: params[:email],
      password: params[:password])
    if @user
      session[:user_id] = @user.id
      flash[:notice] = "ログインしました"
      redirect_to("/users/index")
    else 
      render("index")
    end
  end
end
```
送信されて作動してくれるのか送信ボタンを押してみた。
```
NoMethodError in Users#login
Showing /home/progate/tweet_app/app/views/users/index.html.erb where line #4 raised:

undefined method `each' for nil:NilClass
```
インスタンス変数が空だということはわかった。
### 解決
```users_controller.rb
.
.
.
  def login
    .
    .
    .
    else 
      render("login")
    end
  end
end
```
エラーが消え成功した。

## ヘッダーにユーザーidを表示させる
application.html.erbに書く
```application.html
      <ul class="header-menus">
        <li>
          <%= "現在ログインしているユーザーのid:#{session[:user_id]}" %>
        </li>
.
.
.
```
### ログインしていない場合でも、ヘッダーにユーザーのidが表示されています。
・ログアウトをした後も表示される
わからなかった。

### if session[:user_id]で判断させる
session[:user_id]で判断させることによってログイン中か否かを判断させることができる。