Rails 4 - pundit - how to write if statement to ch

2019-07-13 08:34发布

问题:

I'm trying to learn how to use pundit with my Rails 4 app.

I have a potential use policy. The potential use table has an attribute called :user_id.

I want users to be permitted to update instances if they created them. I'm trying to figure out how to get the update action to work.

My current attempts are shown below.

class PotentialUsePolicy < ApplicationPolicy

    attr_reader :user, :record

  def initialize(user, record)
    @user = user
    @record = record
  end


    def index?
        true if user.is_admin?
    end

    def show?
        true

    end

    def new?
      true
  end

    def create?
        new?
    end

    def update?
        if @user.id == @potential_use.user_id

        # if user.id == potential_use.user_id
            true
        else
            false
        end
    end

    def destroy?
        update?
    end

    def edit?
                true
    end

    def potential_use
        record
    end 

end

When I try these, I keep getting errors saying:

undefined method `user_id' for nil:NilClass

I don't understand why I get this message. When I look in the console, I can see an entry which has a user id.

p = PotentialUse.where(project_id: 26)
  PotentialUse Load (0.5ms)  SELECT "potential_uses".* FROM "potential_uses" WHERE "potential_uses"."project_id" = $1  [["project_id", 26]]
 => #<ActiveRecord::Relation [#<PotentialUse id: 9, comment: "adsfsfdadfasdddxxddbbdd", project_id: 26, created_at: "2016-08-18 23:16:06", updated_at: "2016-08-24 01:06:00", user_id: 1, private_comment: false>]> 
2.3.0p0 :016 > 

When I look in the view (without trying to use the pundit policy, the page renders with all the right content, including the user name (which is accessed by the user_id).

The update action in my potential use controller has:

def update
    authorize @potential_use
    respond_to do |format|
      if @potential_use.update(potential_use_params)
        format.html { redirect_to @project, notice: 'Potential use was successfully updated.' }
        format.json { render :show, status: :ok, location: @potential_use }
      else
        format.html { render @project }
        format.json { render json: @potential_use.errors, status: :unprocessable_entity }
      end
    end
  end

Can anyone see what I've done wrong?

回答1:

To check if a user has permission to perform an action on a policy from a view:

<% if policy(@post).update? %>
  <%= link_to "Edit post", edit_post_path(@post) %>
<% end %>


回答2:

Your error is because you call @potential_use.user_id but @potential_use is never declared in the policy class. You defined potential_use as a method, but in that method you call record, instead of @record.

So, to fix it you should call potential_use instead of @potential_use and change the method to:

def potential_use
    @record
end

Or simply, call @record.user_id instead of @potential_use.user_id.

Besides, as you can see in the Pundit readme, when you inherit from ApplicationPolicy, you don't need to declare:

attr_reader :user, :record

def initialize(user, record)
  @user = user
  @record = record
end

As it is already in the parent class.



回答3:

You access the authorized objects with your accessors. In your example you probaly called

authorize @potential_use

in your controller update action. The update? method on your controller would look like this:

def update?
    user.id == record.user_id
end