下面的代码显示了以不同顺序添加了 before_filters 的两个控制器。结果,控制器具有不同的行为。
当 current_user 为 nil 时(注销):
- FooController -> 重定向到 login_path
- BarController -> 重定向到 root_path
当然,您可以将这两种方法结合起来,让它们更智能,以使这个特定示例消失——但这没有抓住这个问题的重点。
手头的问题是,在 ActionController 中,添加过滤器的顺序是相关的。(你也可以争辩说那个实现不是最好的,但事实就是这样——所以让我们继续吧)
既然 ActionController 就是这样工作的,我想测试一下这种行为。但是,没有必要在每个单独的操作(不是 DRY)上测试之前过滤器的结果。据我所知,实际上重要的是每个 action 上过滤器链的结果顺序。
唯一before_filter :require_user
实际做的是将一个项目注入到回调链中——这就是我应该在我的子类中测试的全部内容——一个额外的项目已添加到链中。我不需要测试require_user
对我的行为产生的影响——它们可以而且应该被存根。
说了这么多,问题来了:是否有一个公共 API 可以返回给定控制器和操作的过滤器链中的方法?这应该包括按适当顺序排列的过滤器之前、之后和周围。
class ApplicationController < ActionController::Base
def require_user
unless current_user
redirect_to login_path and return
end
end
def require_admin
unless current_user.try(:admin?)
redirect_to root_path and return
end
end
end
class FooController < ApplicationController
before_filter :require_user
before_filter :require_admin
end
class BarController < ApplicationController
# reverse the order of the filters
before_filter :require_admin
before_filter :require_user
end