行うこと
・例外処理をする
・エラーメッセージを表示させる
例外処理を行う。
.
.
.
def login
@user = User.find_by email: params[:email], password: params[:password]
if @user
flash[:notice] = "ログインに成功しました。"
redirect_to "/users/#{@user.id}"
else
render "login_form"
end
end
.
.
.
def create
@user = User.new(name: params[:name],email: params[:email],
password: params[:password])
if @user.save
flash[:notice] = "新規作成に成功しました。"
redirect_to "/users/#{@user.id}"
else
render "users/new"
end
end
.
.
.
エラーメッセージをつける
コンソールで実験
irb(main):004:0> user = User.new(name: "saburou", email: "saburou@saburou")
=>
#<User:0x0000000113a11350
...
irb(main):005:0> user.save
TRANSACTION (2.5ms) BEGIN
User Exists? (0.7ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` = 'saburou@saburou' LIMIT 1
User Exists? (0.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`password` IS NULL LIMIT 1
TRANSACTION (0.3ms) ROLLBACK
=> false
irb(main):006:0> user.errors.full_message
/Users/hyoudoumasatomo/.rbenv/versions/3.1.1/lib/ruby/gems/3.1.0/gems/activemodel-7.0.2.3/lib/active_model/errors.rb:419:in `full_message': wrong number of arguments (given 0, expected 2) (ArgumentError)
irb(main):007:0> user.errors.full_messages
=> ["Password can't be blank"]
irb(main):009:0> user = User.new(name: "saburou")
=> #<User:0x0000000115a4baf8 id: nil, name: "saburou", email: nil, passwo...
irb(main):010:0> user.errors.full_messages
=> []
irb(main):011:0> user.save
TRANSACTION (0.3ms) BEGIN
User Exists? (0.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`email` IS NULL LIMIT 1
User Exists? (0.4ms) SELECT 1 AS one FROM `users` WHERE `users`.`password` IS NULL LIMIT 1
TRANSACTION (0.3ms) ROLLBACK
=> false
irb(main):012:0> user.errors.full_messages
=> ["Email can't be blank", "Password can't be blank"]
なるほどerrors.full_messages
は配列なのか。
これでブロック構文を使っている意味がわかった。
これでどう表示されるかがわかった。
ログイン中にする。
session[:user_id] = user.idを使いログイン中にする。
# 他のユーザーの詳細ページで編集できないようにする
条件をつける
そのためにアクションが起こる前にbefore_action
を作動させる。
自分と他のユーザーが違うことを表せばいい
なんだかわからなくなった。
リンクを表示させない。
カレントユーザーでなんとかならないか?
編集のリンクを表示させない。
コントローラのアクションを作動させない。
この2つで完了と考えている。
コントローラの作動が考えてみよう。
ログイン中のユーザーしかコントローラー作動させない。
アクションを作動させる前にbefore_action
があったはずだ。
これを使うとアクションが作動しなくなるからだ。
application_controller
でメソッドを作成し、それをもとに判断させる。
@current_user
のインスタンス変数を作成、それでfalseだった場合はアクションを作動させない。
じゃあどういう風にfalseになるか?
それはsession[:user_id]になかったらだろう。
def set_current_user
@current_user = User.find_by(id: session[:user_id])
end
before_actionをつけていないからか?
progateのテキストに各コントローラがアクションを作動させる前にbefore_action
が作動しない。
class ApplicationController < ActionController::Base
before_action :set_current_user
def set_current_user
@current_user = User.find_by(id: session[:user_id])
end
end
application_controller.rb
に書いておくことで各アクションが作動させる前にインスタンス変数を定義することができる。
思ったこと
なるほどこういうことか
制限するアクションのコントローラーにメソッドを定義するそしてbefore_aciton
を作動させる。
表示させる。
.
.
.
<% if @current_user %>
<li>
<%= @current_user.id %>
</li>
<% end %>
.
.
.
これを書いた。成功!
何回も言うがbefore_action
で準備をしなければ定義していても作動はしない。
editアクションにbefore_actionを備え付ける。
と思った。
が書こうとしたら違うと思った。
メソッドの内容はcurrent_userのidとそれ以外のidの見分けをつけることが大事だからだ。
before_action :check_user, only: [:edit]
.
.
.
def check_user
if @current_user.id != params[:id]
flash[:notice] = "権限がありません"
redirect_to "/"
end
end
編集リンクを押したときは:idのパラメータしかないので
こうすると違うことがわかるのでこれでできた。
成功!
今日はこの辺で。