I'm brand new to rails, and am creating a simple glossary app using Rails 5 with gems Devise and Pundit. I generated an Admin model with Devise; that's the only role that needs to be logged in. I installed Pundit to create policies that would allow me to hide the "Edit," "Destroy," and "New" buttons unless logged in as admin. Glossary App Index
After adding the below policy code to my index.html.erb file to hide the 'Edit' and 'Destroy' buttons, I'm getting an "Undefined method 'current_user'" error.
<tbody>
<% @terms.each do |term| %>
<tr>
<td><%= term.name %></td>
<td><%= term.category %></td>
<td><%= term.definition %></td>
<td><%= link_to 'Show', term, class: 'btn btn-mini' %></td>
<td>
<% if policy(@term).edit? %>
<%= link_to 'Edit', edit_term_path(term), class: 'btn btn-mini' %>
<% end %>
</td>
<td>
<% if policy(@term).destroy? %>
<%= link_to 'Destroy', term, method: :delete, class: 'btn btn-mini', data: { confirm: 'Are you sure?' } %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
Since I didn't generate a "User" model with Devise, but generated an "Admin" model instead, it seemed logical that the error was referring to the word "user" in my new policies. So I replaced "user" with "admin" in my application_policy.rb and terms_policy.rb. Clearly I don't understand what "user" means in this error, as I'm still getting it.
I don't know what exactly you need to see, so here are my models, controllers, and policies:
application_record.rb
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end
admin.rb
class Admin < ApplicationRecord
has_many :terms
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :trackable, :timeoutable, :lockable
end
term.rb
class Term < ApplicationRecord
belongs_to :admin
def self.search(search)
if search
where(["name LIKE ?","%#{search}%"])
else
all
end
end
end
application_controller.rb
class ApplicationController < ActionController::Base
include Pundit
protect_from_forgery with: :exception
before_action :set_current_user
def set_current_user
Term.current_user = current_user
end
end
terms_controller.rb
class TermsController < ApplicationController
before_action :set_term, only: [:show, :edit, :update, :destroy]
before_action :authenticate_admin!, :only => [:new, :edit, :create, :destroy]
# GET /terms
# GET /terms.json
def index
@terms = Term.search(params[:search])
end
# GET /terms/1
# GET /terms/1.json
def show
end
# GET /terms/new
def new
@term = Term.new
end
# GET /terms/1/edit
def edit
@hide_edit_button = true
end
# POST /terms
# POST /terms.json
def create
@term = Term.new(term_params)
respond_to do |format|
if @term.save
format.html { redirect_to @term, notice: 'Term was successfully created.' }
format.json { render :show, status: :created, location: @term }
else
format.html { render :new }
format.json { render json: @term.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /terms/1
# PATCH/PUT /terms/1.json
def update
respond_to do |format|
if @term.update(term_params)
format.html { redirect_to @term, notice: 'Term was successfully updated.' }
format.json { render :show, status: :ok, location: @term }
else
format.html { render :edit }
format.json { render json: @term.errors, status: :unprocessable_entity }
end
end
end
# DELETE /terms/1
# DELETE /terms/1.json
def destroy
@term.destroy
respond_to do |format|
format.html { redirect_to terms_url, notice: 'Term was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_term
@term = Term.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def term_params
params.require(:term).permit(:name, :category, :definition)
end
def verify_is_admin
(current_admin.nil?) ? redirect_to(root_path) :
(redirect_to(root_path) unless current_admin.admin?)
end
end
application_policy.rb
class ApplicationPolicy
attr_reader :admin, :record
def initialize(admin, record)
@admin = admin
@record = record
end
def index?
false
end
def show?
scope.where(:id => record.id).exists?
end
def create?
false
end
def new?
create?
end
def update?
false
end
def edit?
update?
end
def destroy?
false
end
def scope
Pundit.policy_scope!(admin, record.class)
end
class Scope
attr_reader :admin, :scope
def initialize(admin, scope)
@admin = admin
@scope = scope
end
def resolve
scope
end
end
end
terms_policy.rb
class TermPolicy < ApplicationPolicy
def index?
true
end
def create?
user.present?
end
def update?
return true if user.present?
end
def edit?
user.admin?
end
def destroy?
user.admin?
end
end
I've tried implementing suggestions from Access to current_user from within a model in Ruby on Rails, undefined local variable or method `current_user' using devise & rails 3.2, https://code.tutsplus.com/tutorials/authorization-with-pundit--cms-28202, and a smattering of other sources. I'm sure these are all great resources, but at this stage I need something a little more targeted to my project and level of familiarity with Rails.
Let me know what else I can provide. Thanks for your help!
current_admin
acording to the docs If your devise model is something other than User, replace "_user" with "_yourmodel" – inyeset_current_user
in theaplication_controller.rb
I think you have to change the name – inye