【问题标题】:Correcting invalid Resource Routes in Rails更正 Rails 中的无效资源路由
【发布时间】:2012-08-08 14:06:45
【问题描述】:

在 Rails 中使用嵌套资源路由时我注意到的一件事是,从技术上讲,用户可以访问存在子资源(因此可以正确显示)的路由,但是父资源的 id 表示实际上与子资源无关的对象。

例如,在路由users/:user_id/post/:id 中,用户可以输入一个路由,其中​​:user_id 表示没有发布与:id 对应的帖子的用户。

解决此问题的最佳方法是什么,以便在用户访问无效 URL 时,服务器会将用户重定向到正确的 URL?

我已经在我的控制器中放置了一些代码来处理这个问题,但是必须检查每个控制器操作中的路径然后将用户重定向到适当的 url,这有点尴尬,特别是因为每个操作的 URL 帮助程序都不同.

(edit_user_post_path(@user, @post), new_user_post_path(@user, @post))

一定有更好的方法,对吧?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.2 routes nested-routes


    【解决方案1】:

    您应该在所有请求上运行before_filter,以确保用户有效。如果没有,它会抛出ActiveRecord::RecordNotFound 并显示友好的 404 页面。

    然后根据用户的需要抓取帖子,无论是在另一个before_filter 中还是直接在操作中。基于用户的帖子搜索。我下面的示例演示了如何使用另一个 before_filter

    before_filter :find_user_by_user_id
    before_filter :find_post
    
    def show
      # Use @post variable here however you need
    end
    
    private
    
    def find_user_by_user_id
      @user = User.find(params[:user_id])
    end
    
    def find_post
      # This assumes you have an association set up as needed
      @post = @user.posts.where(id: params[:id]).first
    
      if @post.nil?
        # Do whatever you need here
      end
    end
    

    【讨论】:

    • 啊,我明白了。如果我只搜索用户帖子范围内的帖子,我不会有这个问题。到目前为止,我一直在单独搜索帖子。例如。 Posts.find(params[:id])
    【解决方案2】:

    首先您应该知道,ROR 引发的错误将在生产环境中显示消息“对不起,但您要查找的页面不存在”。

    因此,我不会担心这一点。如果您想“捕获”故障并快速重定向到安全区域,您可能有兴趣使用 rescue 方法。

    http://www.simonecarletti.com/blog/2009/12/inside-ruby-on-rails-rescuable-and-rescue_from/

    玩得开心

    【讨论】:

    • 但是什么触发了错误? Rails 是否会自动检查父资源是否正确并做出相应反应?请注意,在我的示例中,Post.find(params[:id]) 将返回一个有效的帖子,User.find(params[:user_id]) 也将是有效的,但 User.find(params[:user_id]).posts.include?(Post.find(params[:id]))Post.find(params[:id]).user == User.find(params[:user_id]) 都将是错误的。
    • 该错误是由关系中返回的 NilClass 触发的。当您尝试查找具有 id 的资源时,假设用户和作为嵌套资源的他的帖子,您将返回一个数组。一旦您选择使用 params[:id] 在 show 操作中将特定帖子从数组中分离出来,它将在数组中搜索 id 时找不到它返回 nil 并呈现 404 输出。
    • 那么......它保存了索引操作中的资源数组,并根据显示操作中返回的资源检查它?我很困惑......仅供参考,在我的开发环境中,当我给出像我的示例中那样的路线时,根本不会返回任何错误。
    • 它将提交的资源与之前提交的关系资源匹配。您在 dev 上没有收到错误的原因是因为您在 development.rb 中设置了 config.consider_all_requests_local = true 如果设置为 false 它将呈现用户友好的输出(404)
    • 这很奇怪。我更改了您提到的变量,但它仍然没有给我任何错误。 (除非父资源根本不存在。)也许你不了解情况,这里有一个例子:用户不知何故最终访问了users/3/posts/5。控制器运行@user = User.find(3)@post = Post.find(5)。 @user 和 @post 都已找到并返回有效的 ActiveRecord 对象。然后 Rails 的哪个部分检查 @user.posts.include?(@post) 是否为真,如果不是则抛出异常?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-12
    • 2011-01-17
    • 2013-09-09
    • 2014-03-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多