LoginSignup
0
0

More than 1 year has passed since last update.

railsアプリを作成 before_action

Posted at

行うこと

・例外処理をする
・エラーメッセージを表示させる

例外処理を行う。

users_controller.rb
.
.
.
  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]になかったらだろう。

application_controller.rb
  def set_current_user
    @current_user = User.find_by(id: session[:user_id])
  end

before_actionをつけていないからか?
progateのテキストに各コントローラがアクションを作動させる前にbefore_actionが作動しない。

application_controller.rb
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を作動させる。

表示させる。

application_controller.rb
.
.
.
       <% if @current_user %>
         <li>
           <%= @current_user.id %>
         </li>
       <% end %>
.
.
.

これを書いた。成功!
何回も言うがbefore_actionで準備をしなければ定義していても作動はしない。

editアクションにbefore_actionを備え付ける。

と思った。
が書こうとしたら違うと思った。
メソッドの内容はcurrent_userのidとそれ以外のidの見分けをつけることが大事だからだ。

users_controller.rb
  before_action :check_user, only: [:edit]
.
.
.
  def check_user
    if @current_user.id != params[:id]
      flash[:notice] = "権限がありません"
      redirect_to "/"
    end
  end

編集リンクを押したときは:idのパラメータしかないので
こうすると違うことがわかるのでこれでできた。
成功!

今日はこの辺で。

0
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
0
0