轨道控制器中的DRY概念

问题描述 投票:0回答:1

我正在做我的第一个rails api服务器。

我已经有了一个控制器,用于我的 User 模型,看起来是这样的。

class UsersController < ApplicationController
  def index
    if current_user.admin?
      @users = User.all
      render json: @users
    else
      render json: { message: 'You do not have the appropriate permissions to access this resource' }, status: 401
    end
  end

  def show
    if User.exists?(@id)
      @id = params[:id]
      if current_user.id.to_s == @id || current_user.admin?
        @user = User.find(@id)
        render json: @user
      else
        render json: { message: 'You do not have the appropriate permissions to access this resource' }, status: 401
      end
    else
      render json: { message: 'Requested resource not found' }, status: 404
    end
  end
end

我想要的是,目前这两个控制器的方法是:

  • /users 只有当发出请求的认证用户是角色时才会获取所有用户 admin
  • /users/:id 读取用户 id 只有当发出请求的认证用户有一个匹配的 id 或有作用 admin

当前的实现打破了DRY理念。原因是处理请求用户是否有权限访问请求的资源的逻辑在两个控制器方法中重复。此外,任何模型的控制器方法 show 将重复检查请求的资源是否存在的逻辑。我也觉得这种实现方式会让控制器变得很胖,而我更希望它们是瘦的。

我想从社区和那些曾经解决过这个问题的人那里了解到的是;为了符合DRY的理念,让控制器瘦下来,最好的方法是什么。

很高兴知道。我正在使用... 设计设备令牌-认证 用于认证。

ruby-on-rails devise devise-token-auth
1个回答
2
投票

你需要使用一些授权宝石,如 cancancan. 这正是你所需要的。而且它的 elseelsif. elsif 后面是条件。


1
投票

您可以使用 github.comvarvetpundit 代替,用于授权。

它与控制器相匹配,你可以用它来将授权移到另一个类中,而不是将授权放在控制器中。

我已经在多个RailsRails-API项目中使用了这个方法,至今没有遇到问题。

与其写上面的代码。你可以用这个来代替。

另外,为了可读性,优先使用早期返回而不是嵌套的if。

在你的控制器中。

class UsersController < ApplicationController
  def index
    authorize User # This will call the policy that matches this controller since this is UsersController it will call `UserPolicy`

    @users = User.all

    render :json => @users
  end

  def show
    @user = User.find_by :id => params[:id] # Instead of using exists which query the data from db then finding it again, you can use find_by which will return nil if no records found.

    if @user.blank?
      return render :json => {:message => 'User not found.'}, :status => 404
    end

    authorize @user # This will call the policy that matches this controller since this is UsersController it will call `UserPolicy`

    render :json => @user
  end
end

在你的Policy中

class UserPolicy < ApplicationPolicy
  def index?
    @user.admin? # The policy is called in controller then this will check if the user is admin if not it will raise Pundit::NotAuthorizedError
  end

  def show?
    @user.admin? || @record == @user # The policy is called in controller then this will check if the user is admin or the user is the same as the record he is accessing if not it will raise Pundit::NotAuthorizedError
  end
end

在您的ApplicationController中

class ApplicationController < ActionController::API
  include Pundit

  rescue_from Pundit::NotAuthorizedError, :with => :show_forbidden



  private

  def show_forbidden exception
    return render :json => {
      :message => 'You are not authorized to perform this action.'
    }, :status => 403
  end
end
© www.soinside.com 2019 - 2024. All rights reserved.