[英]How to allow only the author of a post edit or delete it in Ruby on Rails?
I have a user model and a question model. 我有一个用户模型和一个问题模型。
In the user model: 在用户模型中:
has_many :questions
The question model: 问题模型:
belongs_to
in my questions/show.html.erb 在我的问题/ show.html.erb
<% if @question.user == current_user %>
<%= link_to 'Edit', edit_question_path(@question) %> | <%= link_to 'Destroy', @question, method: :delete, data: { confirm: 'Are you sure you want to delete this job?' } %>
<%= link_to 'Back', questions_path %>
<% else %>
<%= link_to 'Back', questions_path %>
<% end %>
How can only the user that authored the question edit and delete it? 只有编写问题的用户如何编辑并删除它?
Take a look at CanCan , the authorization gem by Ryan Bates of Railscasts . 看看CanCan ,这是Railscasts的Ryan Bates的授权瑰宝。 It's great for Rails authorization needs.
这对Rails授权需求非常有用。
First, you'll create an Ability
class that defines all of the abilities in the application. 首先,您将创建一个
Ability
类,该类定义应用程序中的所有功能。
class Ability
include CanCan::Ability
def initialize(user)
can :manage, Question, user_id: user.id
end
end
Then, you'll be able to easily integrate authorization into your controllers. 然后,您将能够轻松地将授权集成到您的控制器中。
class QuestionsController < ApplicationController
def update
authorize! :manage, @question
...
end
def destroy
authorize! :manage, @question
...
end
end
And also customize your views. 并定制您的观点。
<% if can? :manage, @question %>
<%= link_to 'Edit', edit_question_path(@question) %> | <%= link_to 'Destroy', @question, method: :delete, data: { confirm: 'Are you sure you want to delete this job?' } %>
<% end %>
All you need in your controller is: 您在控制器中所需的全部是:
def destroy
@question = current_user.questions.find(params[:id])
@question.destroy
render ... #anything you want to render
end
The previous code will ensure that an user can only delete his own questions. 先前的代码将确保用户只能删除自己的问题。 If the id of the question doesn't belongs to the user no question will be deleted and it would throw and
ActiveRecord::RecordNotFound - Internal Server error
. 如果问题的id不属于用户,则不会删除任何问题,它会抛出
ActiveRecord::RecordNotFound - Internal Server error
。 You can add a begin - rsecue block
to catch this exception an handle it as you want. 您可以添加一个
begin - rsecue block
以根据需要捕获此异常并对其进行处理。
def destroy
begin
@question = current_user.questions.find(params[:id])
@question.destroy
render or redirect_to ....
rescue Exception ActiveRecord::RecordNotFound
flash[:notice] = 'not allow to delete this question'
redirect_to ....
end
end
Other simple way is to add a before filter in your controller 其他简单的方法是在控制器中添加一个前置过滤器
before_filter :require_authorization, only: [:delete]
...
def destroy
@question = current_user.questions.find(params[:id])
@question.destroy
render or redirect_to ....
#With the before filter this code is only going to be executed if the question belongs to the user
end
...
private
def require_authorization
redirect_to :root unless current_user.questions.find_by_question_id(params[:id])
#Use the find_by to avoid the ActiveRecord::RecordNotFound and get a nil instead in case the question id doesn't belong to a question of the user
end
you can try changing your if
to the following: 您可以尝试将
if
更改为以下内容:
<% if current_user.questions.include?(@question) %>
Also you can take a look at :inverse_of 你也可以看看:inverse_of
Then in your Edit and Delete actions in the controller you can again check for the right user before showing the edit form or deleting the question. 然后,在控制器的“编辑”和“删除”操作中,您可以在显示编辑表单或删除问题之前再次检查合适的用户。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.