24
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Ruby on Rails】投稿したユーザーのみが編集できるようにする

Last updated at Posted at 2020-09-07

目標

  • URLのベタ打ちでの他ユーザーの編集を防ぐ
  • view画面にそもそも表示させない

開発環境

ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

前提

※ ▶◯◯ を選択すると、説明等が出てきますので、
  よくわからない場合の参考にしていただければと思います。

考え方

基本的には、
①if文でcurrent_userなどで絞るか、
②current_userに紐づくモデルを抽出するかで
投稿したユーザーのみが編集可能。
※viewでは前者を、controllerでは後者で実装。

controllerの編集

前提の状態での記述

app/controllers/posts_controller.rb
	def edit
		@post = Post.find(params[:id])
	end

	def update
    @post = Post.find(params[:id])
		if @post.update(post_params)
      redirect_to new_post_path
    else
      render :edit
    end
	end

	def destroy
		@posts = Post.all
		@post = Post.find(params[:id])
		@post.destroy
	end

このままではURLをベタ打ちすると編集、削除が可能に。
そこで下記のように記述。

app/controllers/posts_controller.rb
  def edit
    @post = Post.find(params[:id])
    unless @post.user == current_user
      redirect_to  new_post_path
    end
  end

  def update
    @post = Post.find(params[:id])
    if @post.user != current_user
      redirect_to  new_post_path
    else
      if @post.update(post_params)
        redirect_to new_post_path
      else
        render :edit
      end
    end
  end

  def destroy
    @posts = Post.all
    @post = Post.find(params[:id])
    if @post.user != current_user
      redirect_to  new_post_path
    else
      @post.destroy
    end
  end
補足 unless 条件 => 条件がfalseの場合を定義。

ただしこれでは記述が多くなり、修正する場合に手間が必要。
そこでbefore_actionを活用。

app/controllers/posts_controller.rb

before_action :ensure_user, only: [:edit, :update, :destroy]

...
	
  def edit
  end

  def update
    if @post.update(post_params)
      redirect_to new_post_path
    else
      render :edit
    end
  end

  def destroy
    @post.destroy
    redirect_to new_post_path
  end

  private
  def ensure_user
    @posts = current_user.posts
    @post = @posts.find_by(id: params[:id])
    redirect_to new_post_path unless @post
  end

...

補足 before_actionを活用することにより、アクションが読み込まれる前に行う動作を指定することができる。 定義はストロングパラメーターで行い、current_userでない場合はreditrct_toを定義。

viewsの編集

URLベタ打ち以前にそもそもユーザー誤認を防ぐために画面で表示をしない方が望ましい。

app/views/posts/new.html.erb
<% @posts.each do |post| %>
	<tr>
		<td><%= post.user.name %></td>
		<td><%= post.title %></td>
		<td><%= post.body %></td>
		<td><%= link_to "詳細", post_path(post) %></td>
		<td><%= link_to "編集", edit_post_path(post) %></td>
		<td><%= link_to "削除", post_path(post), method: :delete %></td>
	</tr>
<% end %>

この部分を修正。

app/views/posts/new.html.erb
<% @posts.each do |post| %>
  <tr>
    <td><%= post.user.name %></td>
    <td><%= post.title %></td>
    <td><%= post.body %></td>
    <td><%= link_to "詳細", post_path(post) %></td>
    <% if post.user == current_user %>
      <td><%= link_to "編集", edit_post_path(post) %></td>
      <td><%= link_to "削除", post_path(post), method: :delete %></td>
    <% else %>
      <td></td>
      <td></td>
    <% end %>
  </tr>
<% end %>

結論

 controllerとviewを編集することにより、他ユーザーの編集を防ぐことが可能。

24
30
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
24
30

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?