Pundit role based strong params

Pundit provides a great way to map your controller actions to policies. You can reject the entire action based on a user’s role. But what if you have a scenario where a user with more privileges sends additional params that normal users cannot send back?

Let’s say we only allow Administrators to edit a certain text field and reject other users from editing them. Pundit provides permitted_attributes that can be used in conjunction with strong parameters.

In your policy class, define a method called permitted_attributes

class PostPolicy
  def permitted_attributes
    if user.admin?
      [:title, :body, :pinned_to_homepage]
    else
      [:title, :body]    
    end
  end
end

Now in our controller, we can do:

class PostsController
  def update
    @post.update(post_params)
  end

  def post_params
    params.require(:post).permit(policy(@post).permitted_attributes)
  end
end

Now only Administrators can edit the pinned_to_homepage attribute in the post.