1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rails コールバック・フィルタ

Last updated at Posted at 2020-12-11

現在筆者は書籍を参考にタスク管理アプリをつくっています。
今回はその中でもログイン機能の一部分を実装した手順を書いていこうと思います。

ログインしていなければタスク管理を利用できなくする

アプリのタスク管理機能を、ユーザーがログインしていなければ利用できないようにしていきます。
前提としてログイン、ログアウト機能の実装が終わっていることとします。

ユーザーがログインしていなければ利用できないようにするには、コントローラのフィルタ(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を次のような形に編集していきます。

app/controllers/application_controller.rb
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などを利用する。

app/controllers/sessions_contorller.rb
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 速習実践ガイド

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?