2020/12/16 railsチュートリアル9章後半、10章
9章残り
remember meをレイアウトに追加
チェックボックス
<%= f.label :remember_me, class: "checkbox inline" do %> <%= f.check_box :remember_me %> <span>Remember me on this computer</span> <% end %>
ログインフォームにチェックボックスを追加。
paramas[:session][:remember_me]に、チェックしてたら文字列の'1'、チェックしていなければ'0'が入る。
if params[:session][:remember_me] == '1' remember(user) else forget(user) end
三項演算子で書くと
params[:session][:remember_me] == '1' ? remember(user) : forget(user)
10章
ユーザーを更新する
<%= form_with(model: @user, local: true) do |f| %>
ユーザー登録時と全く同じコードだがどうやってupdateアクション(PATCH)と認識しているのか
"@user.new_record?がtrueのときにはPOSTを、falseのときにはPATCHを使います。"
とのこと。
htmlを見ると、
...method="post"...value="patch"
とふたつのリクエストの種類がある
今はブラウザではgetかpostしか実装していない(このリクエストしか送れない)
そこでrailsがPATCHリクエストに偽装している。
ユーザーの編集
def update @user = User.find(params[:id]) if @user.update(user_params) #updateでえいや else render 'edit' end end
@user.updateはupdate_attributeみたいなものか
render 'edit'をする頃には、updateアクションを行ったので@users.errorsにデータが入っているので、renderしたときにエラ〜メッセージが出てくる
allow_nil
現時点ではvalidationでパスワード入ってないとエラーになるが、updateのする時には入力されていない可能性もあるので、 変更する
validates :password, presence: true, length: { minimum: 6 }, allow_nil: true
has_secure_passwordで別にvalidationがあるので未入力のまま作成されることは避けられる。
認可
正しいユーザーだけがアクセスできるようにする。
まず、ログインしてなかったらログイン促すようにする。
"before_action" => リクエストがきたらactionを実行前に行うアクションを指定する
before_action :logged_in_user, only: [:edit, :update]
ログインしてるかをチェック
before_action :correct_user, only: [:edit, :update]
正しいユーザーかチェック
before_actionを2つに分けているのは、まずログインしていないと、ユーザーが正しいか確認することができないため。
複数ある場合は上から順番に実行する。
def correct_user @user = User.find(params[:id]) #アクセスしようとしているページのIDで検索した@userは redirect_to(root_url) unless @user == current_user #current_userと一致しているか end
リファクタリングすると、
# ヘルパーメソッド定義して def current_user?(user) user && user == current_user #渡されたユーザーがnilではなく、current_userと一致すればtrueを返す end def correct_user @user = User.find(params[:id]) #アクセスしようとしているページのIDで検索した@user redirect_to(root_url) unless current_user?(@user) #@userがnilではなく、current_userと一致しなければ end
フレンドリーフォワーディング
ログインした後にもともと行きたかったとこにリダイレクトしてあげる
# 記憶した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? #session変数に:forwading_urlをキーとしてリクエストしたURLを保存 end
before_action :logged_in_userの中に、store_locationメソッドを入れることで、ログインしていない人が行きたかったURLを保存(した上で、ログインページにリダイレクトする)
ログインするとき(セッションを作成する時)に、session[:fowarding_url]が存在すればそこにリダイレクトして欲しいので、session controllerのcreateアクションのリダイレクトを変更する
request.get?
このコードでフォームから送ったリクエストがgetリクエストかどうかを確認している。
before_actionで制限している2つのうち、patchリクエスト(update)ではなくgetリクエスト(edit)の時だけ保存できたらいい。