Rails ログイン/ログアウト/アクセス制限機能について
今回の記事では
- ログイン機能
- ログアウト機能
- ユーザー名の表示
- アクセス制限機能
について書いていきます
- ログイン機能
ログイン機能は長くなるので工程を書いておきます
- get "login"とpost "login"ルーティングの作成
↓
- users/login_form.html.erbビューを作成
↓
- パスワードカラムを追加
↓
- フォームの送信に関して書く
↓
- usersコントローラに中身を書いていく
まずルーティングから
get "login" => "users#login_form
post "login" => "users#login"
先頭に付いているgetとpostが違うのあれば名前が一緒でもいいそうです。
次にusersフォルダにlogin_form.html.erbファイルを作成します
そこにユーザー情報を送信出来るようにinputなどを書いていくのですがその前にpasswordを追加したいので前回やったようにusersテーブルにpasswordカラムを追加します
ターミナルで↓を書き
rails g migration add_password_to_users
db/migrateフォルダ内の"更新データの日付_add_password_to_users.rb"ファイル内に↓と書きます
def change
add_column :users, :password, :string
end
これでパスワードカラムがDBに追加されました
rails db:migrate
を忘れずに!
次はフォームの送信が出来るようにlogin_form.html.erbファイルにメールアドレスや名前等(ここでは省略)に加えてパスワードを追加します
<%= form_tag("/login") do %>
〜各種送信するフォームの中身(email,name等)〜
<p> パスワード</p>
<input type="password" name="password" value="<%= @password %>">
<% end %>
type="password"は入力した文字が黒塗りで見られないようにするもので、value="<%= @password %>"は初期値を表示するためです
@passwordは後でコントローラ内で定義します
次はusersコントローラに"login_form"と"login"を定義して、"login"の中身を書いていきます
def login
@user = User.find_by("email: params[:email], password: params[:password]")
if @user
session[:user_id] = @user.id
flash[:notice] = "ログインしました"
redirect_to("/posts/index")
else
@error_message = "〜"
@email = params[:email]
@password = params[:password]
render("users/login_form")
end
end
まずフォームから送信された情報をfind_by("〜")で取得します
次に情報が取得出来た後、@userが存在する場合、
session[:キー名]というのはこれに代入した情報を送信し続ける変数です(ここではユーザーの情報を送信することでページを移動しても情報が保持されログイン状態が続くという仕組み)
else以降は@error_messageでエラーメッセージを表示し、@email = params[:…]と@password = params[:…]はビュー内のvalue="〜"で初期値を表示するためのものです
- ログアウト機能
まずはルーティング
post "logout" => "users#logout"
sessionの値を変更する場合もDBの変更の時と同じようにpostを使います
ではコントローラを書いていきます
def logout
session[:user_id] = nil
flash[:notice] = "〜"
redirect_to("/login")
end
session[] = nilにすることで送信する情報を空にすることが出来ます(ターミナルでのrails server起動時にctrl+Cを押して接続をキャンセルするみたいな感じ?)
後はログアウトリンクに忘れずに{method: "post"}を指定してくださいね
- ユーザー名の表示
applicationコントローラ内で定義したアクションをbefore_actionで他のコントローラやビューでも使えるというものなのですが、
このbefore_actionを使ってユーザー名の表示をしていきます
まずapplicationコントローラ内に
before_action :set_current_user
〜省略〜
def set_current_user
@current_user = User.find_by(id: session[:user_id])
end
を定義します
これは@current_userでログイン中のユーザーidを取得しているという意味です
そしてbefore_action :〜で他のアクションでも使えるようにします
そしてlayout/application.html.erbファイル内のヘッダーリンク部分に
<il>
<%= link_to(@current_user.name, "/users/#{@current_user.id}") %>
</li>
と書けばログイン中のユーザー名が表示されます
- アクセス制限
これも基本的には
applicationコントローラ内で定義したアクションを各コントローラ内でbefore_actionを使うものになります。
例えばログインしていないユーザーがログインしているページに入ろうとした場合に
def authenticate_user
if @current_user == nil
redirect_to("/login")
end
end
と定義しておけば、これをログインして欲しく無いページのアクションに指定しておけば、このアクションが発動されてアクセスが制限されるというわけです
例:usersコントローラ内のedit,updateアクションでこのアクション(authenticate_user)を行いたい場合、usersコントローラ内で
before_action :authenticate_user, {only: [:edit, :update]}
と適用したい任意のアクションをonlyで指定します
後はログイン中のユーザーが別のユーザーの編集を出来ないように、(ここではusersコントローラ内でのみ適用させるので)usersコントローラ内で
before_action :ensure_correct_user,
{only: [:edit, :update]}
〜省略〜
def ensure_correct_user
if @current_user.id != params[:id].to_i
redirect_to("/posts/index")
end
end
を定義します
ポイントは@current_userが params[:id]で受け取った値と比較する場合に params[:~]は文字列でしか受け取れないので.to_iを使って数値に変換する必要があるところです
今日はこれで以上です。
初めて3000文字以上書きましたが時間がかかり疲れました…
いつも1000文字当たり1時間くらいかかるので(今回は2.5時間くらい)なかなか更新するのは大変ですが、良いアウトプットだと思い頑張って続けます💪
いつも読んでくださりありがとうございます🙏