現在筆者は書籍を参考にタスク管理アプリをつくっています。
今回はその中でもログイン機能の一部分を実装した手順を書いていこうと思います。
ログインしていなければタスク管理を利用できなくする
アプリのタスク管理機能を、ユーザーがログインしていなければ利用できないようにしていきます。
前提としてログイン、ログアウト機能の実装が終わっていることとします。
ユーザーがログインしていなければ利用できないようにするには、コントローラのフィルタ(Filter)という機能を使います。
フィルタというのはアクションを処理する前後に、任意の処理を挟むことができる。
アクションの前処理として他の機能へのリダイレクトを実装すると、リダイレクトが行われ、アクションには到達しない。
そのため、特定の状況の時にだけアクションが利用できるように制限するという目的のために前処理のフィルタが使用される。
フィルタはコールバックと似たような機能なので違いがわかる参考記事を貼っておきます
https://k-koh.hatenablog.com/entry/2020/02/10/222058
そもそもなんでコールバックとフィルタの機能って使うの?という方にはこちらの記事がおすすめです。(ここではコールバックの必要性のみ)
https://tech.kitchhike.com/entry/2018/06/30/232400
フィルタもモデルのコールバックと同様にフィルタとしてメソッドを登録して実際にそのメソッドを実装するというやり方で追加する。
今回は、login_requiredという名前のメソッドをアクションの前に呼ばれるフィルタとして登録することにする。
アクションの前に呼ばれるフィルタを登録するには、before_actionメソッドを使う。
before_actionにはonlyオプションなどで適用するアクションを指定することもできる。今回は指定せずに全てのアクションに対して有効にする。
なお、タスク管理をログインしていない時に利用させないだけであれば、login_requiredフィルタの追加はTasksControllerで行えば良い。
しかし、他の機能にもそのような制限を付けたいことも予想できるため、全機能に共通の処理を記述することに適したApplicationControllerに記述する。
ApplicationControllerを次のような形に編集していきます。
class ApplicationController < ActionController::Base
helper_method :current_user
before_action :login_required
private
def current_user
@current_user ||= User.find_by(id: session[:user_id]) if session[:user_id]
end
def login_required
redirect_to login_url unless current_user
end
end
これで、アプリケーション内の全てのアクション処理前に、ユーザーがログイン済みかどうかのチェックが入り、
ログイン済みではなかった場合にはログイン画面を表示するようになりますが、これが正しく動作するためには1点だけ解決すべき問題がある。
今のままでは、ログイン画面を表示するためのアクションに対してもlogin_requiredフィルタが実行されてしまうため、
アプリケーションのどのURLをリクエストしても無限にredirectが行われてしまう。
これを避けるため、SessionControllerはログインしていなくても利用できるようにしていきたいと思います。
親クラスなどですでに定義済みのフィルタを通らないようにするには、skip_before_actionなどを利用する。
class SessionsController < ApplicationController
skip_before_action :login_required
def new
end
def create
user = User.find_by(email: session_params[:email])
if user&.authenticate(session_params[:password])
session[:user_id] = user.id
redirect_to root_url, notice: 'ログインしました。'
else
render :new
end
end
def destroy
reset_session
redirect_to root_url, notice: 'ログアウトしました'
end
private
def session_params
params.require(:session).permit(:email, :password)
end
end
これで、ログインしていないユーザーに利用制限をかける実装は完了です。
次回は、ログインしているユーザーのデータだけを扱えるようにしていきたいと思います。
参考書籍:現場で使える Ruby on Rails5 速習実践ガイド