Rails Policies(Pundit) Links only displaying if user.admin?

1.1k views Asked by At

So I have an issue with policies. When a user creates a topic they should be able to see edit and delete buttons for that topic however those buttons are not displaying. But, if the user's role is defined as admin then they can in fact see the edit and delete topic buttons.

Hoping to get some insight on this:


application_policy.rb:

class ApplicationPolicy
  attr_reader :user, :record

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

  def index?
    false
  end

  def show?
    scope.where(:id => record.id).exists?
  end

  def create?
    user.present?
  end

  def new?
    create?
  end

  def update?
    user.present? && (record.user == user || user.admin?)
  end

  def edit?
    update?
  end

  def destroy?
    update?
  end

  def scope
    record.class
  end

  class Scope
    attr_reader :user, :scope

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

    def resolve
      scope
    end
  end
end

topic_policy.rb:

class TopicPolicy < ApplicationPolicy
  def index?
    true
  end
end

user.rb(model):

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable

  mount_uploader :avatar, AvatarUploader
  has_many :topics, dependent: :destroy
  has_many :bookmarks, dependent: :destroy
  has_many :likes, dependent: :destroy

  validates :name, presence: true

  def admin?
    role == 'admin'
  end

  def moderator?
    role == 'moderator'
  end

  def member?
    role == 'member'
  end

  def liked(bookmark)
    likes.where(bookmark_id: bookmark.id).first
  end
end

Lastly here is a chunk of the show view which contains the buttons:

<div class="row landing-top">
  <h1 class="lato-dark text-center"><%= topic_hash %></h1>
  <div class="col-md-2 text-center">
    <%= link_to topics_path, class: 'btn btn-default btn-sm' do %>
        <span class="glyphicon glyphicon-circle-arrow-left black inliner"></span>
        <h5 class="inliner lato-dark">Back to Topics</h5>
    <% end %>
  </div>
  <div class="col-md-8">
    <div class="js-bookmarks">
      <%= render partial: 'bookmarks/bookmark', collection: @bookmarks %>
    </div>
  </div>
  <div class="col-md-2">
    <div class="text-center">
      <% if policy(@topic).update? %>
      <!-- Button trigger modal -->
        <button type="button" class="btn button-3d-edit" data-toggle="modal" data-target="#edit">
          <span class="glyphicon glyphicon-pencil"></span>
          Edit Topic
        </button>
      <% end %>
      <% if policy(@topic).destroy? %>
        <%=link_to @topic, method: :delete, class: 'btn button-3d-delete', data: { confirm: 'Are you sure you want to delete this topic?' } do %>
          <span class="glyphicon glyphicon-remove"></span>
          Delete Topic
        <% end %>
      <% end %>
      <% if policy(@bookmarks).create? %>
      <!-- Button trigger modal -->
        <button type="button" class="btn button-3d" data-toggle="modal" data-target="#new-bookmark">
          <span class="glyphicon glyphicon-plus"></span>
          New Bookmark
        </button>
      <% else %>
        <button type="button" class="btn button-3d" data-toggle="modal" data-target="#notSignedIn">
          <span class="glyphicon glyphicon-plus"></span>
          New Bookmark
        </button>
      <% end %>
    </div>
  </div>
</div>
1

There are 1 answers

0
Jeff Wilkey On BEST ANSWER

So in the process of trying to cheat my way around it I found an answer. Topics were being created with a user_id of nil which is why Pundit was not able to track whether a specific topic was created by a specific user or not.

So in my topics_controller file I made the addition of @topic.user = current_user which then began setting a user_id for created topics allowing Pundit to track who created that particular topic.

def create
    @topic = Topic.new(topic_params)
    @topic.user = current_user
    @new_topic = Topic.new
    authorize @topic
    if @topic.save
      flash[:notice] = "Topic was created successfully."
    else
      flash[:error] = "There was an error creating your topic. Please try again."
    end

    respond_to do |format|
      format.html
      format.js
    end
  end