第9章,练习6,Michael Hartl的Ruby on Rails教程:解决方案是什么?

时间:2013-01-14 06:21:15

标签: ruby-on-rails-3.2 railstutorial.org ruby-1.9.3

在Michael Hartl的 Ruby on Rails Tutorial,2nd Ed ,第9章练习6中,说:

  

登录用户没有理由访问新用户并在其中创建操作   用户控制器。安排将这些用户重定向到   根网址,如果他们确实尝试点击这些网页。

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

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

我尝试过使用do / end块,添加用户属性的哈希等。上面的代码段已添加到the official sample code中的第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测试。 The code I have created as I follow this tutorial is available at github.

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

2 个答案:

答案 0 :(得分:2)

我现在正在阅读本教程,并且正在进行这项练习,所以我当然不是专家。但是,我正在以不同的方式解释请求。据我了解,如果任何登录用户尝试用户新用户或创建操作,而不仅仅是非管理员,请求将重定向到根页面。

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

中描述的before_filter

答案 1 :(得分: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块中。如果我不这样做,那么代码会继续显示,如创建操作所示。对于新操作,这不是一个问题,因为在简单化的三元之后,它只分配了一个实例变量。

总之,我只需要保罗提供一个非常好的线索,并且睡个好觉。谢谢。