I've been working on a social link aggregator site and have run into a wall with regards to admin permissions.
Currently all users can edit and destroy their own posts (admins included) but an error is thrown when an admin tries to delete a post created by another user.
While I'm fairly well versed in ruby my rails knowledge is severely lacking so it may well be something extremely simple staring me in the face.
When attempting to edit a post the error is: undefined method `model_name' for TrueClass:Class
When attempting to delete a post the error is: undefined method `destroy' for true:TrueClass
Here are relevant parts of my links_controller.rb:
def update
respond_to do |format|
if @link.update(link_params)
format.html { redirect_to @link, notice: 'Link was successfully updated.' }
format.json { render :show, status: :ok, location: @link }
else
format.html { render :edit }
format.json { render json: @link.errors, status: :unprocessable_entity }
end
end
end
def destroy
@link.destroy
respond_to do |format|
format.html { redirect_to links_url, notice: 'Link was successfully destroyed.' }
format.json { head :no_content }
end
end
def authorized_user
@link = current_user.links.find_by(id: params[:id]) || current_user.admin?
redirect_to links_path, notice: "Not authorized to edit this link" if @link.nil?
end
The user model:
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :links
has_many :posts
acts_as_voter
validates :twitter, :twitter => { :format => :username_with_at, allow_blank: true }
validates :avatar_url, :url => { allow_blank: true }
end
And the admin model:
class Admin < ActiveRecord::Base
devise :database_authenticatable, :trackable, :timeoutable, :lockable
end
If you need any more information I'll be happy to provide it, alternatively if any of the code I've posted is irrelevant to the issue let me know and I'll remove it from the post.
@link
will be true
if current_user is admin, it's not correct, @link
should be an instance of Link
@link = current_user.links.find_by(id: params[:id]) || current_user.admin?
You should use an authorization gem to check permission such as action_access, cancan, cancancan, pundit,...
problem is the following line
@link = current_user.links.find_by(id: params[:id]) || current_user.admin?
here if the user is admin then the value of @link will be 'true'
so @link.destroy
becomes true.destroy
which is not a valid function
undefined method `model_name' for TrueClass:Class
This basically means you've populated a variable with true
instead of an object. You know this already; it should direct you towards what to look for to identify the problem:
@link = current_user.links.find_by(id: params[:id]) || current_user.admin?
The error here is that you're calling current_user.admin?
. Because your initial argument is returning false, Ruby is referring to the last. the admin?
method must be returning true
.
--
Authorization
The fix for this is something called Authorization .
You'll probably know this already; in the sense of Rails, authorization is not handled very well at all at the moment. The best implementations have been CanCan by Ryan Bates (of Railscasts fame).
In short, what you need is some sort of system which examines who you are, and allows you to perform an action based on your credentials.
If you handled this manually, you'd do this:
@link = current_user.links.find_by(id: params[:id]) || (Link.find(params[:id]) if current_user.admin?) #-> not tested!!!
If you used something something like CanCan (now updated to CanCanCan
) you could use:
#app/controllers/your_controller....
def destroy
@link = Link.find params[:id]
@link.destroy if can? :destroy, @link
end
#app/models/ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
can :manage, :all if user.has_role? :admin
can [:update, :destroy], Link, user_id: user.id
end
end
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.