如何过滤rails中的对象,以便只有创建它的用户或管理员才能销毁该对象?

时间:2018-02-11 18:27:57

标签: ruby-on-rails ruby crud before-filter

我有一个简单的rails应用程序,用户可以在其中创建引号(例如,“两件事是无限的:宇宙和人类的愚蠢;我不确定宇宙。” - Albert Einstein等。)

我只想创建报价的用户或管理员能够编辑和删除报价。

目前我有一个前置过滤器,用于设置创建如下所示的引用的用户:

before_action :correct_user, only: :destroy

这是我的Quotes controller

class QuotesController < ApplicationController
  before_action :set_artist,   only: [:show, :edit, :update, :destroy]
  before_action :logged_in_user, only: [:create, :new, :destroy, :update, :edit ]
  before_action :correct_user,   only: :destroy

  def index
    @quotes = Quote.all.paginate(page: params[:page], per_page: 12)
  end

  def show
  end

  def new
    @quote = Quote.new
  end

  def create
    @quote = current_user.quotes.build(quote_params)
    if @quote.save
      flash[:success] = "Quote created!"
      redirect_to @quote
    else
      render :new
    end
  end

  def edit
  end

  def update
    if @quote.update(quote_params)
      flash[:success] = "Quote updated"
      redirect_to @quote
    else
      render :edit
    end
  end

  def destroy
    @quote.destroy
    flash[:success] = "Quote deleted"
    redirect_back(fallback_location: browse_path)
  end

  private

    def set_artist
      @quote = Quote.find(params[:id])
    end

    def quote_params
      params.require(:quote).permit(:content, :source, :topic_id, :speaker_id)
    end

    def correct_user
      @quote = current_user.quotes.find_by(id: params[:id])
      redirect_to root_url if @quote.nil?
    end
end

在Rails中执行此操作的惯用方法是什么?我应该这样做:

def correct_user
  if user.admin?
    @quote = current_user.quotes.find_by(id: params[:id])
  else
   @quote = current_user.quotes.find_by(id: params[:id])
  end
  redirect_to root_url if @quote.nil?
end

有没有更简洁或Rails方式来做到这一点,我错过了?此外,您如何确保只有创建报价的用户才能删除或编辑报价?我的correct_user方法是否涵盖了这一点?

2 个答案:

答案 0 :(得分:2)

我会在行动之前设置两个。

before_action :resource, only: [:edit, :update, :destroy]
before_action :allow_admin, only: [:edit, :update, :destroy]

首先会找到报价资源

def resource
  @quote = current_user.quotes.find_by(id: params[:id])
end

其他允许管理员访问资源

def allow_admin
  if current_user.admin? && @quote.nil?
    @quote = Quote.find_by(id: params[:id])
    # Search all quotes, as admin has access to all
  elsif @quote.nil?
    redirect_to root_url
  end
end

答案 1 :(得分:1)

我认为您可以检查用户是否为admin或者user.id是否与quote.user_id相同,在这种情况下您返回true,使用||如果其中任何一个返回true表达式返回true,因此您可以执行以下操作:

def correct_user
  current_user.admin? || current_user.id == @quote.user_id
end

因此,如果用户不是管理员或不是引用作者/所有者,您可以创建一个重定向的帮助方法:

before_action :check_permission, only: %i[edit destroy]

def correct_user
  current_user.admin? || current_user.id == @quote.user_id
end

def check_permission
  redirect_back(fallback_location: browse_path) unless correct_user
end

使用之前的回调,如果将这两个表达式中的某些表达式评估为真,则可以检入编辑和销毁以及任何其他表达式。