2

在我的控制器中,我经常使用这样的东西来验证 a 是否project真的属于给定的user

private

def authorized_user
  @project = Project.find(params[:id])
  redirect_to root_path unless current_user?(@project.user)
end

这很好用,因为用户 A 看不到用户 B 的项目(他被转发到根页面)。

但是,这只有project在请求的 URL 确实存在时才有效。

例如,该 URLhttp://localhost:3000/projects/1将显示用户的项目或转发到根 URL(如果另一个用户尝试访问该项目)。

但是当我尝试访问数据库中根本不存在的项目,例如:

http://localhost:3000/projects/777

...我收到一个丑陋的ActiveRecord::RecordNotFound错误:

Couldn't find Person with id=777

在这里改善用户体验的最佳方法是什么?

我还没有真正部署过 Rails 项目,所以我什至不知道这个错误在生产模式下会是什么样子。

有人可以帮忙吗?

谢谢...

4

4 回答 4

5

我个人喜欢用这个:

@project = Project.where(id: params[:id]).first

如果项目不存在,@project则为零。

于 2013-02-14T19:39:58.013 回答
1

尝试:

class ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, :with => :render_404
  # Render 404 page when record not found
    def render_404      
       render :file => "#{RAILS_ROOT}/public/404.html", :status => 404
    end
end
于 2013-02-15T07:21:33.590 回答
1

根据您想要的处理方式,您可以使用

@project = Project.find_by_id(params[:id])

如果没有找到任何记录,这将使 @project 为零,您将必须手动处理该案例。

另一种解决方案是抛出一个 404 ,这很有意义,因为资源不存在。您可以使用以下命令在任何控制器(或应用程序控制器)中轻松完成此操作:

rescue_from ActiveRecord::RecordNotFound, :with => :not_found

def not_found
  raise ActionController::RoutingError.new('Not Found')
end

这将导致类似:

class ApplicationController < ..
  rescue_from ActiveRecord::RecordNotFound, :with => :not_found

  def not_found
    raise ActionController::RoutingError.new('Not Found')
  end
end

后一种解决方案将向用户显示默认的 404(未找到)错误页面。在第一种情况下,您拥有更多控制权,但代价是到处都这样做

希望有帮助。

于 2013-02-14T19:44:04.347 回答
1

首先,为了避免未经授权的用户访问项目,你应该限定你的 find 方法:

current_user.projects.find(params[:id])

这样,您将在开发中收到“找不到带有 id 的项目”错误。为避免这种情况,您可以使用:

current_user.projects.find_by_id(params[:id])

它返回nil而不是异常,但是有充分的理由说明您通常不应该这样做。在编写良好的 Rails 应用程序中,任何用户唯一会访问他不应该访问的项目的时间是当他手动更改 url 中的 id 时。您希望在您的日志中报告这一点,而不是默默地跳过。

最后,要抛出 403 Forbidden 而不是 404 Not Found,您可以考虑使用许多授权 gem 之一(cancan想到的是 Ryan Bates)。

编辑:哦,在生产中,ActiveRecord::RecordNotFound 将呈现 404.html 页面,也就是这些不是您正在寻找的项目。

于 2013-02-14T22:53:40.210 回答