gpt4 book ai didi

ruby-on-rails - rails : Keeping user spoofing checks DRY

转载 作者:太空宇宙 更新时间:2023-11-03 18:02:30 24 4
gpt4 key购买 nike

我正在使用 Ruby on Rails 编写一个博客应用程序,这有点缺乏创意。我的 PostsController 包含一些代码,确保登录用户只能编辑或删除他们自己的帖子。

我尝试将此代码分解为一个私有(private)方法,其中包含一个用于显示 flash 消息的参数,但是当我这样做并通过编辑另一位作者的帖子对其进行测试时,我得到了一个 ActionController::DoubleRenderError - “每次操作只能呈现或重定向一次”。

我怎样才能保留这些支票 DRY ?显而易见的方法是使用前置过滤器,但 destroy 方法需要显示不同的 flash。

这里是相关的 Controller 代码:

before_filter :find_post_by_slug!, :only => [:edit, :show]

def edit

# FIXME Refactor this into a separate method
if @post.user != current_user
flash[:notice] = "You cannot edit another author’s posts."
redirect_to root_path and return
end
...
end

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

# FIXME Refactor this into a separate method
if @post.user != current_user
flash[:notice] = "You cannot edit another author’s posts."
redirect_to root_path and return
end
...
end

def destroy
@post = Post.find_by_slug(params[:slug])

# FIXME Refactor this into a separate method
if @post.user != current_user
flash[:notice] = "You cannot delete another author’s posts."
redirect_to root_path and return
end
...
end

private
def find_post_by_slug!
slug = params[:slug]
@post = Post.find_by_slug(slug) if slug
raise ActiveRecord::RecordNotFound if @post.nil?
end

最佳答案

前过滤器方法仍然是一个不错的选择。您可以使用 Controller 的 action_name 方法访问请求的操作。

before_filter :check_authorization

...

protected

def check_authorization
@post = Post.find_by_slug(params[:slug])
if @post.user != current_user
flash[:notice] = (action_name == "destroy") ?
"You cannot delete another author’s posts." :
"You cannot edit another author’s posts."
redirect_to root_path and return false
end
end

对不起中间那个三元运算符。 :) 当然你可以做任何你喜欢的逻辑。

如果你愿意,你也可以使用一个方法,并在失败时通过显式返回来避免双重渲染。这里的关键是返回,这样你就不会重复渲染。

def destroy
@post = Post.find_by_slug(params[:slug])
return unless authorized_to('delete')
...
end

protected

def authorized_to(mess_with)
if @post.user != current_user
flash[:notice] = "You cannot #{mess_with} another author’s posts."
redirect_to root_path and return false
end
return true
end

您可以(在我看来)通过拆分行为的不同部分(授权、处理错误授权)来进一步简化它,如下所示:

def destroy
@post = Post.find_by_slug(params[:slug])
punt("You cannot mess with another author's post") and return unless author_of(@post)
...
end

protected

def author_of(post)
post.user == current_user
end

def punt(message)
flash[:notice] = message
redirect_to root_path
end

就个人而言,我更喜欢将所有这些日常工作卸载到插件中。我个人最喜欢的授权插件是 Authorization .在过去的几年里,我使用它取得了巨大的成功。

这将重构您的 Controller 以在以下方面使用变体:

permit "author of :post"

关于ruby-on-rails - rails : Keeping user spoofing checks DRY,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/901772/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com