Rails 4 位专家

Rails 4 with Pundit

我正在尝试在 Rails 4.

中制作一个应用程序

我想使用 Pundit 进行授权。我还使用 Devise 进行身份验证,使用 Rolify 进行角色管理。

我有一个用户模型,正在制定我的第一个策略,遵循本教程:

https://www.youtube.com/watch?v=qruGD_8ry7k

我有一个用户控制器:

    class UsersController < ApplicationController

before_action :set_user, only: [:index, :show, :edit, :update, :destroy]

  def index
    if params[:approved] == "false"
      @users = User.find_all_by_approved(false)
    else
      @users = User.all
    end

  end

  # GET /users/:id.:format
  def show
    # authorize! :read, @user
  end

  # GET /users/:id/edit
  def edit
    # authorize! :update, @user
  end

  # PATCH/PUT /users/:id.:format
  def update
    # authorize! :update, @user
    respond_to do |format|
      if @user.update(user_params)
        sign_in(@user == current_user ? @user : current_user, :bypass => true)
        format.html { redirect_to @user, notice: 'Your profile was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # GET/PATCH /users/:id/finish_signup
  def finish_signup
    # authorize! :update, @user 
    if request.patch? && params[:user] #&& params[:user][:email]
      if @user.update(user_params)
        @user.skip_reconfirmation!
        sign_in(@user, :bypass => true)
        redirect_to @user, notice: 'Your profile was successfully updated.'
      else
        @show_errors = true
      end
    end
  end

  # DELETE /users/:id.:format
  def destroy
    # authorize! :delete, @user
    @user.destroy
    respond_to do |format|
      format.html { redirect_to root_url }
      format.json { head :no_content }
    end
  end

  private
    def set_user
      @user = User.find(params[:id])
    end

    def user_params
      params.require(:user).permit(policy(@user).permitted_attributes)
      # accessible = [ :first_name, :last_name, :email ] # extend with your own params
      # accessible << [ :password, :password_confirmation ] unless params[:user][:password].blank?
      # accessible << [:approved] if user.admin
      # params.require(:user).permit(accessible)
    end

end

这是我第一次了解用户政策。

class UserPolicy < ApplicationPolicy


  def initialize(current_user, user)
    @current_user = current_user
    @user = user

  end

  def index?
    @current_user.admin? 
  end

  def show?
    @current_user.admin? 
  end

  def edit?
    @current_user.admin? 
  end

  def update?
    @current_user.admin?  
  end

  def finish_signup?
    @current_user = @user
  end

  def destroy?
    return false if @current_user == @user
    @current_user.admin? 
  end

private
  def permitted_attributes
      accessible = [ :first_name, :last_name, :email ] # extend with your own params
      accessible << [ :password, :password_confirmation ] unless params[:user][:password].blank?
      accessible << [:approved] if user.admin
      params.require(:user).permit(accessible)
  end

end

我的问题是:

  1. 教程显示了一个叫做 attr_reader 的东西。我是从rails 4开始学习rails的,所以我不知道这些词是什么意思。我认为这与在控制器中将用户参数列入白名单的旧方法有关,所以我认为我不需要将其包含在我的用户策略中。对吗?

  2. 我必须按照上面的方式初始化用户模型是否正确(或者只有用户以外的模型才会这样,因为我正在初始化 current_user,它可能已经初始化了用户?

  3. 是否有必要将强参数移动到策略中,或者如果我将它们留在控制器中是否可行?

  1. The tutorial shows something called attr_reader. I have started learning rails from rails 4 so I don't know what these words mean. I think it has something to do with the old way of whitelisting user params in the controller, so I think I don't need to include this in my user policy. Is that correct?

不,这很重要。

attr_reader 创建实例变量和相应的方法,return每个实例变量的值。 - 来自Ruby 官方文档

基本上如果你这样做

class A
   attr_reader :b
end

a = A.new

您可以执行 a.b 来访问 b 实例变量。这很重要,因为在每个策略中,您可能允许 read 访问实例变量。 @current_user@user 是实例变量。

  1. is it right that i have to initialise the user model the way I have above (or is that only the case in models other than user, since I'm initialising current_user, it might already get the user initialised?

您必须手动初始化它。目前,您的操作方式是正确的。好的。

  1. is it necessary to move the strong params to the policy, or will this work if I leave them in the controller?

这是选择的问题。即使您将它保存在控制器中,它也会起作用。仅当您想以非常复杂的方式将属性列入白名单时才转向策略。

注意:devicepunditrolify gem 效果很好,但它们共享一些相同的功能,因此请注意并保持一致。

例如,您可以使用devise_for :users , :students , :teachers,这将提供3个不同的链接来登录各自的资源。你可以用它做很多事情。您可以使用 authenticate 方法根据资源进一步验证 url。检查 https://github.com/plataformatec/devise/wiki/How-To:-Define-resource-actions-that-require-authentication-using-routes.rb 这种事情也可以通过 pundit 策略和 rolifyroles 来完成。