更新TopicsController以允许主持人更新主题,但不能创建或删除

时间:2015-10-03 19:50:09

标签: ruby-on-rails ruby

我正在创建类似于Reddit的网站。我想允许主持人能够更新主题,但无法创建或删除主题。我知道我需要更新TopicsController,但我不确定如何。我的主要问题是,我不确定如何使代码具体到足以确保主持人只能更新;不要像管理员那样删除或创建主题。

我目前的代码如下:

class PostsController < ApplicationController

  before_action :require_sign_in, except: :show
  before_action :authorize_user, except: [:show, :new, :create]

  def show
    @post = Post.find(params[:id])
  end

  def new
    @topic = Topic.find(params[:topic_id])
    @post = Post.new
  end

  def create
    @post.body = params[:post][:body]
    @topic = Topic.find(params[:topic_id])
    @post = @topic.posts.build(post_params)
    @post.user= current_user
    if @post.save
      flash[:notice] = "Post was saved"
      redirect_to [@topic, @post]
    else
      flash[:error] = "There was an error saving the post. Please try again."
      render :new
    end
  end

  def edit
    @post = Post.find(params[:id])
  end

  def update
    @post = Post.find(params[:id])
    @post.assign_attributes(post_params)

    if @post.save
      flash[:notice] = "Post was updated."
      redirect_to [@post.topic, @post]
    else
      flash[:error] = "There was an error saving the post. Please try again."
      render :edit
    end
  end

  def destroy
    @post = Post.find(params[:id])

    if @post.destroy
      flash[:notice] = "\"#{@post.title}\" was deleted successfully."
      redirect_to @post.topic
    else
      flash[:error] = "There was an error deleting the post."
      render :show
    end
  end

  private

  def post_params
    params.require(:post).permit(:title, :body)
  end

  def authorize_user
    post = Post.find(params[:id])

    unless current_user == post.user || current_user.admin?
      flash[:error] = "You must be an admin to do that."
      redirect_to [post.topic, post]
    end
  end

end

我已经为枚举角色添加了一个主持人角色。

如果这看起来非常基本,我道歉......但它让我感到难过!

提前致谢!

2 个答案:

答案 0 :(得分:0)

我可以使用一些自定义解决方案来回答,但最好使用更加结构化和社区审核的方法:使用cancan进行授权。

答案 1 :(得分:0)

作为tompave noticed,你可以使用cancan gem。 我个人更喜欢pundit

在过去,我曾经在代码中直接定义权限:在控制器,视图甚至模型中。但这是非常糟糕的做法。当你的应用程序增长时,你会迷失:你更新了一个视图,但你应该在控制器中进行相同的更改,有时也在模型中进行更改。它很快变得绝对无法管理,你不知道你的用户能做什么,不能做什么。

另一方面,

Pundit提供了中心位置 - 政策 - 用于定义用户可以执行的操作。然后,视图和控制器可以使用这些策略。

例如,如果您需要定义Post的政策,则只需创建app/policies/post_policy.rb文件:

 class PostPolicy
    attr_reader :user
    attr_reader :post

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

    def author?
      post.user == user
    end

    def update?
      author? || user.admin? || user.moderator?
    end

    def create?
      author? || user.admin?
    end

    def destroy?
      author? || user.admin?
    end

    # etc.
 end

现在,只要您需要检查用户执行操作的能力,您只需调用:

# in controller
def update
  @post = Post.find(params[:id])
  authorize @post
  # do whatever required
end

# in view
<% if policy(post).update? %>
  <%= link_to 'Edit Post', post_edit_path(post) %>
<% end %>

正如您所看到的,Pundit非常容易理解,它使用与配置相同的约定&#34;作为Rails的方法。同时它非常灵活,允许您测试几乎任何东西。

您肯定需要Pundit或任何类似的宝石来管理您雄心勃勃的应用中的权限。