2

我有一个用户模型和一个问题模型。

在用户模型中:

has_many :questions

问题模型:

belongs_to 

在我的问题/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 %>

只有创建问题的用户才能编辑和删除它?

4

3 回答 3

6

看看CanCan , Railscasts的 Ryan Bates 的授权宝石。它非常适合 Rails 授权需求。

首先,您将创建一个Ability定义应用程序中所有功能的类。

class Ability
  include CanCan::Ability

  def initialize(user)
    can :manage, Question, user_id: user.id
  end
end

然后,您将能够轻松地将授权集成到您的控制器中。

class QuestionsController < ApplicationController
  def update
    authorize! :manage, @question
    ...
  end
  def destroy
    authorize! :manage, @question
    ...
  end
end

并自定义您的视图。

<% 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 %>
于 2013-03-03T17:09:34.470 回答
2

您在控制器中需要的只是:

def destroy
  @question = current_user.questions.find(params[:id])
  @question.destroy

  render ... #anything you want to render
end

前面的代码将确保用户只能删除他自己的问题。如果问题的 id 不属于用户,则不会删除任何问题,它会抛出 and ActiveRecord::RecordNotFound - Internal Server error。您可以添加一个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

其他简单的方法是在控制器中添加一个前置过滤器

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
于 2013-03-03T17:28:44.090 回答
0

您可以尝试将您的更改if为以下内容:

<% if current_user.questions.include?(@question) %>

你也可以看看:inverse_of

然后在控制器中的编辑和删除操作中,您可以在显示编辑表单或删除问题之前再次检查正确的用户。

于 2013-03-03T16:47:49.163 回答