简体   繁体   中英

Rails 4 - Pundit - create policy

I'm trying to figure out how to use pundit in my Rails 4 app.

I have a profile view in which I want to display a link to create a new project, subject to pundit authorisation.

I have tried each of the following formulations:

 <%# if policy(Project.new).create? %>
                            <%# if policy(Project).create? %>
                            <%# if policy(@project).create? %>
                            <%# if policy(Projects).create? %>
                            <% if policy(project).create? %>


                             <%= link_to 'CREATE A PROJECT', new_project_path, :class=>"btn btn-info"  %>
                            <% end %> 

The association between project and profile is:

Project

belongs_to :profile

Profile

has_many :projects, dependent: :destroy

My project policy has:

def new?
        true
        # create?
    end

    def create?
        true

    end

when I try using this line in the profile view : <% if policy(Project).create? %> <% if policy(Project).create? %>

I get an error that says:

wrong number of arguments (given 2, expected 0)

when I try using this line in the profile view : <% if policy(@project).create? %> <% if policy(@project).create? %>

I get an error that says:

wrong number of arguments (given 2, expected 0)

when I try using this line in the profile view : <% if policy(Projects).create? %> <% if policy(Projects).create? %>

I get an error that says:

unable to find policy of nil

when I try using this line in the profile view : <% if policy(project).create? %> <% if policy(project).create? %>

I get an error that says:

undefined local variable or method `project' for <#:0x007faf5255d468> Did you mean? project_url

Is there something special I need to do to test the project authorisation if the view page is in a different model (eg profile, testing authorisation for that profile as to whether it can create a project)? I'm stuck and guessing as to how to solve this problem.

In my projects controller, I have a create method with:

def create
    @project = Project.new(project_params)
    @project.profile = current_user.profile

    respond_to do |format|
      if @project.save
        format.html { redirect_to @project }
        format.json { render :show, status: :created, location: @project }
      else
        format.html { render :new }
        format.json { render json: @project.errors, status: :unprocessable_entity }
      end
    end
  end

The initialiser for the policy:

class ProjectPolicy < ApplicationPolicy

    attr_reader :user, :record

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

It looks like your code may not have the necessary instance variables. Inside your show method you should have a @project - you can use Pundit to check wether the user can create it.

As you dont appear to have a @project , you can try this instead:

<% if policy(Project.new).create? %>

You could also try using a symbol instead:

policy(:project)

<% if policy(:dashboard).show? %>
  <%= link_to 'Dashboard', dashboard_path %>
<% end %>

Do you have a policy defined like so?

# app/policies/project_policy.rb
class ProjectPolicy < Struct.new(:user, :project)
  # ...
end

Usually I will use another class, say ViewPolicy, for the purpose in view:

class ViewPolicy < Struct.new(:user, :views)

    def items_index?
        user.has_role?(:sales)
    end

end

So I can do something like this:

<% if policy(:views).items_index? %>
  <%= link_to("Items", items_path) %>
<% end %>

very similar to @Kieran Andrews

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM