##はじめに
Railsを学習した直後のアウトプット時、いざアクセス制限機能を実装しようと試みた際に、何をどうしたらいいのか思い浮かばなかったのが悔しかったため
次に同じ轍を踏まないよう、自分用にアクセス制限の実装順序を整理してみました。
##まず、アクセス制限って「何を」実装する機能なのん?
例えば、Webアプリケーションにおいてログイン機能を実装した後などで
ユーザーがログインしている場合と、ログインしていない場合とで、ユーザーが使える機能を制限する機能。
##それじゃあ、「どうすれば」実装できるのか?
・ユーザーがログインしている場合で一つ条件式を記述し、制限用の処理を記述する。
・ユーザーがログインしていない場合でもう一つ条件式を書き、制限用の処理を記述する。
例
if #(ユーザーがログインしている場合の条件式)
redirect_to("URL") #制限用の処理
end
##コードは「どこに」記述するん?
簡単な掲示板アプリ作成を例として、「ユーザーがログインしていない場合」のアクセス制限機能を実装したいとします。
1.Railでは、主にルーティング→アクション→ビューの順でデータのやり取りが行われるので
2.例えば、ログインしていないユーザーに投稿機能のアクセス制限を実装したい場合は
3.投稿機能用のアクションにデータが渡されたタイミングで、ログインしていないユーザーを弾けば良いということになりますので
4.投稿用のアクション最上部に、「ユーザーがログインしていない場合」の条件式と処理を記述してあげます。
5.そうすれば、投稿用のアクションが実行される前に、アクセス制限の処理が実行されます。
よってコードをどこに記述すればいいのかと言うと、制限を実装したい機能のアクション内の上部、ということになります。
例
def #投稿用アクション
if #(ユーザーがログインしていない場合の条件式)
redirect_to("URL") #指定したURLに飛ばす
end
#投稿用の処理
end
##before_actionとは文字通り、actionのbeforeに実行される
ただ投稿制限の他にも、投稿を閲覧する機能や投稿を編集する機能なども制限したい場合もあるかと思います。
その際、制限したいアクション全てに対し条件式を書こうとするのは、同じ記述をすることになり好ましくない上に面倒臭いです……。
そこで、全てのアクションに対して一括で処理を行う方法が存在します。
どのように全てのアクションに対し一括で処理を行うかというと、applicationコントローラに処理を記述してあげます。
applicationコントローラとは、全てのコントローラを管理している親のような存在です。
画像の一番上にあるのが、applicationコントローラで
その直下に他のコントローラが羅列され、applicationコントローラの処理を継承しています。
そのため、applicationコントローラで記述された処理は、別のコントローラで実行されることになります。
ただし注意する点があり、「before_action :メソッド名」という処理をコントローラ内の上部に記述してあげる必要があります。
言葉だけでは伝わりにくいと思いますので、コード例を記述してみます。
before_action :#メソッド名
# ログインしていない場合のアクセス制限
def #メソッド名
if #(アクセスしたユーザーがログインしていない場合の条件式)
redirect_to("URL") #指定したURLに飛ばす
end
end
このようにapplicationコントローラ内に「before_action :メソッド名」と記述してあげることで、メソッド内で定義した処理が全てのコントローラのアクションが実行される前に実行されることになります。
before_actiontに関しては文字通り、全てのアクションの前に実行される処理という風に覚えておけば、用途をしっかり理解して使えるようになるかと思います。
##before_actionを特定のアクションにだけ適用させる方法があるだと!?
全てのアクションへ処理が適用されるとは言っても、特定のアクションにだけアクセス制限を適用させたいという場合もあるでしょう。
そう言った場合には、特定のアクションにだけアクセス制限の処理を適用させる方法が存在します。
applicationコントローラ内で記述した「before_action :メソッド名」を
適用させたいアクションが記述されているコントローラの上部に記述した上で
メソッド名に続けて「, {only: [:アクション名, :アクション名,...]}」として
[ ]内に、各コントローラ内のアクセス制限を適用させたいアクション名を記述してあげることで、特定のアクションにだけアクセス制限を適用することができます。
例
before_action :#メソッド名, {only: [:投稿用アクション名, 投稿表示アクション名,...]}
def #投稿用アクション名
#処理
end
def #投稿表示用アクション名
#処理
end
こうすることにより、各々アクションが実行される前に、before_actionの処理が呼び出され、各アクションへのアクセス制限が可能となります。
##まとめ
「アウトプットでアクセス制限を実装したい!」となった場合、考える順序として
1.まずアクセス制限とは、ログイン機能実装後に「ログインしているユーザーへの機能制限」や「ログインしていないユーザーへの機能制限」を行うこと。
2.「投稿を制限したい」「投稿の閲覧を制限したい」など、「どんなアクセス制限」を実装したいか思い浮かべる。
3.もし投稿機能を制限したいなら、「投稿用のアクション」など、コードを記述すべき場所を思い浮かべる。
4.該当アクション内の上部に、「ユーザーがログインしていない場合は〜〜の処理を行う」などの「条件式」を記述する。
5.他の機能も制限したいけれど、複数個に渡って同じ記述をするのは面倒臭いな……。
6.複数アクションに制限を掛けたい場合は、applicationコントローラを使えば、一つの記述で済むことを思い出す。
7.applicationコントローラ内に、条件式とアクセス制限の処理を記述する。
8.各コントローラ内のアクションが実行される前に、アクセス制限処理を実行しなければならないことを思い出す(before_action :メソッド名)。
(9.特定のアクションにアクセス制限を掛けたい場合の処理は、「 before_action :メソッド名, {only: [:アクション名, :アクション名,...]} 」を、各コントローラ内の上部に記述する。)
##最後に 周りくどい説明をしてきましたが、このあたりは基礎の基礎ですし 始めはRailsそのもののデータやり取りの仕組みを理解することが重要だと思ったので、今回のように遠回りするような解説をさせて頂きました。 僕も慣れるまでは、この思考手順で学習を進めるつもりです。
##参考
Progate