1

在 Michael Hartl 的Ruby on Rails 教程,第 2 版,第 9 章的练习 6 中,说:

登录用户没有理由访问用户控制器中的新操作和创建操作。如果他们确实尝试访问这些页面,请安排将此类用户重定向到根 URL。

如何为此编写 rspec 测试?我试过这个

  describe "POST on Users#create" do
    before { post users_path }
    specify { response.should redirect_to(root_path) }
  end

我尝试过使用 do/end 块,添加用户属性的哈希等。上面的代码片段已添加到官方示例代码的第 162 行。他们都给我这个错误:

Failures:

  1) Authentication authorization as non-admin user POST on Users#create 
     Failure/Error: before { post users_path }
     AbstractController::DoubleRenderError:
       Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like "redirect_to(...) and return".
     # ./app/controllers/users_controller.rb:27:in `create'
     # ./spec/requests/authentication_pages_spec.rb:72:in `block (5 levels) in <top (required)>'

Finished in 2.72 seconds
88 examples, 1 failure

至于限制对用户控制器中新操作和创建操作的访问的实际目标,我通过添加以下行来解决它们:

admin_user if signed_in?

我知道这很有效,因为我手动测试了它。唯一的问题是我无法为其编写 rspec 测试。我按照本教程创建的代码可在 github 上找到。

为什么我会收到此错误?我究竟做错了什么?解决办法是什么?谢谢你。

4

2 回答 2

2

我自己只是在阅读教程,并且正在做这个确切的练习,所以我当然不是专家。但是,我对请求的解释与您不同。据我了解,如果任何登录用户尝试用户新建或创建操作,则请求将重定向到根页面,而不仅仅是非管理员。

无论如何,我见过的最优雅的解决方案是使用https://stackoverflow.com/a/11287798/1008891中所述的 before_filter

于 2013-02-02T03:03:11.750 回答
1

保罗,谢谢你的线索。我解决了这个问题。

我试图通过添加来解决目标

admin_user if signed_in?

虽然这似乎在浏览器中工作,但在后台还有其他事情发生。在仔细查看我的创建操作后,这是我所做的更改,并且 rspec 测试开始起作用:

    diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 6e0fec8..53f8325 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -8,8 +8,8 @@ class UsersController < ApplicationController
   end

   def new
-    admin_user if signed_in?
-    @user = User.new
+    signed_in? ? admin_user : @user = User.new
+    #@user = User.new
   end

   def show
@@ -17,14 +17,17 @@ class UsersController < ApplicationController
   end

   def create
-    admin_user if signed_in?
-    @user = User.create(params[:user])
-    if @user.save
-      sign_in @user
-      flash[:success] = "Welcome to the Sample App!"
-      redirect_to @user
-    else
-      render 'new'
+    if signed_in?
+        admin_user
+      else
+      @user = User.create(params[:user])
+      if @user.save
+        sign_in @user
+        flash[:success] = "Welcome to the Sample App!"
+        redirect_to @user
+      else
+        render 'new'
+      end
     end
   end

解决方案是将代码包含在完整的 if/else 块中。如果我不这样做,则代码似乎会继续执行,正如创建操作所证明的那样。这对于新操作来说不是问题,因为在简单的三元之后,它只分配了一个实例变量。

总之,我只需要保罗提供一个很好的线索,然后睡个好觉。谢谢你。

于 2013-01-14T17:19:28.293 回答