[Day11 Rails Tutorial]第十章途中|ユーザー情報の編集に制限[10.2.1〜10.2.3]

Day11です!もうすぐで2週間!

9月も時間の流れが早いですね。

今日はシュレッダーを紙でつまらせ、時間を取られ、全然チュートリアルできませんでした。

もう1枚ずつしか入れない。

今日もがんばっていきましょー!

読んでいただいている方、いつもありがとうございます!

初心者なもので、たまに間違った内容もあるかと思います。

その際にはコメントやTwitterでご指摘いただけると幸いです!

 

[Day11]第十章10.2.1〜10.2.3作業ログ

ユーザーの認可

前回でユーザー情報の編集ができるようになった。

でも今はその編集ページのURLにアクセスすればだれでも情報を変更できるようになっている。

ログインしている自分の情報しか変更できないように変えよう。

 

edit,updateアクションの前に、ログインユーザーかどうか確認

edit,updateアクションの前に、ログインユーザーかどうかチェックするアクションを経由するように設計。

before_action :logged_in_user, only: [:edit, :update]

このbefore_actionを使うことによって、それが実現できる。

第二引数のonly: [:edit, :update]を設定すると、特定のアクションの前だけ、before_actionを適用できる。

:logged_in_userアクションは、current_userが存在しているかをチェックするlogged_in?アクションを使って、ログイン済みかどうかチェック。

ログインしていなかったら、フラッシュメッセージとともにトップページへリダイレクトするように。

実際のコードはこんな感じ。

users_controller.rb
class UsersController < ApplicationController
  before_action :logged_in_user, only: [:edit, :update]
  ...
  private
  ...
    # beforeアクション
    # ログイン済みユーザーかどうか確認
    def logged_in_user
      unless logged_in?
        flash[:danger] = "Please log in."
        redirect_to login_url
      end
    end
end

 

自分のユーザー情報だけ編集可能に

今はログイン済みであれば、他のユーザー情報も変更できてしまう。

さっきのbefore_actionを使って、current_userと編集対象のユーザーが同じであればOK、違っていたらリダイレクトするようにする。

編集対象のユーザーは編集ページのURL(users/4/edit)から、params[:id]でとってこれる。

実際のコードはこんな感じ。

users_controller.rb
class UsersController < ApplicationController
  before_action :logged_in_user, only: [:edit, :update]
  ...
  private
  ...
    # 正しいユーザーかどうか確認
    def correct_user
      @user = User.find(params[:id])
      redirect_to(root_url) unless @user == current_user
    end
end

 

フレンドリーフォワーディング

ちょっと細かいところだけど、もしログインしていないユーザーが編集ページにアクセスしようとした時、ユーザーがログインした後はその編集ページにリダイレクトされるようにが親切な設計。

つまり、リダイレクト先はユーザーが開こうとしていたページにするのがベター。

このフレンドリーフォワーディングを実装するには、開こうとしていたページ情報を変数に保存する必要がある。

普通の変数だとアクションが終われば、忘れてしまうので、一時的にデータを蓄えておけるsessionを使ってあげる。

session[:forwarding_url]にリクエスト先立ったURLを保存してあげればOK。

またリクエスト先URLはrequest.original_urlで所得できる。

sessions_helper.rb
module SessionsHelper
  ...
  # 記憶したURL (もしくはデフォルト値) にリダイレクト
  def redirect_back_or(default)
    redirect_to(session[:forwarding_url] || default)
    session.delete(:forwarding_url)
  end
  # アクセスしようとしたURLを覚えておく
  def store_location
    session[:forwarding_url] = request.original_url if request.get?
  end
end

あとは、ログインユーザーかどうか確認してるところに、store_locationアクション、情報を更新するcreateアクションに、redirect_back_or(default)を設定してあげればOK。

 

タケシなりの演習の回答

何故editアクションとupdateアクションを両方とも保護する必要があるのでしょうか? 考えてみてください。

editアクションは個人情報保護のため(emailが覗かれる)、updateは情報の変更を阻止するため。

もしかしたら、ユーザー情報の変更を阻止するだけなら、updateアクションを制限するだけでもいいのかも。

 

上記のアクションのうち、どちらがブラウザで簡単にテストできるアクションでしょうか?

ブラウザでのチェックがしやすいのは、GETリクエストで調べられるeditアクションの方。

PATCHアクションはURLに乗せて情報を送れないので、ブラウザでのチェックは難しい。

 

フレンドリーフォワーディングで、渡されたURLに初回のみ転送されていることを、テストを書いて確認してみましょう。次回以降のログインのときには、転送先のURLはデフォルト (プロフィール画面) に戻っている必要があります。

リダイレクト後、session[:forwarding_url]がnilになっていればOK。

users_edit_test.rb
require 'test_helper'
class UsersEditTest < ActionDispatch::IntegrationTest
  ...
  test "successful edit with friendly forwarding" do
    get edit_user_path(@user)
    log_in_as(@user)
    assert_redirected_to edit_user_url(@user)
    assert_nil session[:forwarding_url]
    name  = "Foo Bar"
    email = "foo@bar.com"
    ...
  end
end

 

[Day11]まとめ

  • 学習範囲:10.2.1〜10.2.3
  • 学習時間:1時間40分
  • 総学習時間:46時間20分
  • 反省点:家のシュレッダーをつまらせ、3時間以上時間を取られました。。反省。おかげで全然チュートリアルできなかった。
  • 備考:特になし

読んでいただいている方、いつもありがとうございます!

初心者なもので、たまに間違った内容もあるかと思います。

その際にはコメントやTwitterでご指摘いただけると幸いです!

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です