varvet / pundit

Minimal authorization through OO design and pure Ruby classes
MIT License
8.29k stars 632 forks source link

Access params hash in controller #528

Closed ivanelrey closed 6 years ago

ivanelrey commented 6 years ago

I am using ajax-datatables-rails gem which requires me to pass params hash to a class.

def index
  respond_to do |format|
    format.html
    format.json { render json: UserDatatable.new(params) }
  end
end

I get the following error: NoMethodError (undefined method `params' for ):

Is there any way to configure pundit so I can access params in a specific method?

Linuus commented 6 years ago

I don’t understand what this has to do with pundit?

I think the problem is in your UserDatatable class.

ivanelrey commented 6 years ago

Yes correct, my fault. thanks.

BSorbus commented 6 years ago

Btw, how correctly use Pundit Scope with ajax-datatables-rails gem?

ivanelrey commented 6 years ago

@BSorbus This is what I did:

UserPolicy::Scope.new(@current_user, User).resolve

Don't forget to include Pundit

Linuus commented 6 years ago

@ivanelrey Is there a reason you can't just do policy_scope(User) instead?

ivanelrey commented 6 years ago

@Linuus As I remember I couldn't use policy_scope(User) in UserDatatable class because current_user was undefined.

BSorbus commented 6 years ago

@ivanelrey Is there a reason you can't just do policy_scope(User) instead?

Where to use policy_scope()?

class ProjectsController < ApplicationController
  ...
  def datatables_index
    respond_to do |format|
      format.json{ render json: ProjectDatatable.new(view_context) }
    end
  end
  ...
end
class ProjectDatatable < AjaxDatatablesRails::Base
  def_delegators :@view, :link_to, :project_path,

  def view_columns
    @view_columns ||= {
      id:     { source: "Project.id", cond: :eq, searchable: false, orderable: false },
      number: { source: "Project.number", cond: :like, searchable: true, orderable: true },
      user:   { source: "User.name", cond: :like, searchable: true, orderable: true }
    }
  end

  def data
    records.map do |record|
      {
        id:         record.id,
        number:     link_to(record.number, project_path(record.id)),
        user:       record.user.try(:name)
      }
    end
  end

  private
  def get_raw_records
    Project.joins(:user).all
  end
end
ivanelrey commented 6 years ago

@BSorbus You need to use policy_scope on the Project table.

Try something like this: 1) Include pundit in your class include Pundit

2) In your get_raw_records method try: ProjectPolicy::Scope.new(@current_user, User).resolve.joins(:user)

If you get error that the current_user is undefined: Try in your controller:

format.json{ render json: ProjectDatatable.new(view_context, user: current_user) }

and override the initializer of your ProjectDatatable class

def initialize(params, opts = {})
    @current_user = opts[:user]
    super
  end
BSorbus commented 6 years ago

Thanks