在 current_user 上调用名称方法导致测试错误(ruby 在 rails 上)
Calling name method on current_user causes testing error (ruby on rails)
我完成了 Michael Hartl 的 Rails 教程的第 11 章,之后我开始寻找使用 thumbs_up gem 为微博添加一些声誉和投票功能的方法。
我想在导航栏的小方框(如 Stack Overflow)中显示当前用户的声誉。我可以使用以下方法获得用户名和信誉以正常显示:
<li class="rep_box"><%= current_user.name %> <%= current_user.karma %> </li>
该页面工作正常并正确呈现用户名和声誉,但现在我遇到了几个错误并失败了。如果我删除上面的代码行,一切都会再次正常工作。
这是错误的一个例子——它们几乎都是一样的:
>ERROR["test_should_get_home", StaticPagesControllerTest, 2016-04-09 04:36:31 -0400]
test_should_get_home#StaticPagesControllerTest (1460190991.59s)
ActionView::Template::Error: ActionView::Template::Error: undefined method `name' for nil:NilClass
app/views/layouts/_header.erb:6:in `_app_views_layouts__header_erb__1475229759153232172_2241208160'
app/views/layouts/application.html.erb:12:in `_app_views_layouts_application_html_erb__4357373253304461109_2216429940'
test/controllers/static_pages_controller_test.rb:9:in `block in <class:StaticPagesControllerTest>'
app/views/layouts/_header.erb:6:in `_app_views_layouts__header_erb__1475229759153232172_2241208160'
app/views/layouts/application.html.erb:12:in `_app_views_layouts_application_html_erb__4357373253304461109_2216429940'
test/controllers/static_pages_controller_test.rb:9:in `block in <class:StaticPagesControllerTest>'
undefined method `name' for nil:NilClass
这意味着 current_user
在调用 name
时是 nil
。确保此时已正确分配,错误就会消失。
你需要sign_in
一个用户才有current_user
.
你可以这样做:
let(:curr_user) { User.create(...attrs...) }
sign_in curr_user
Devise includes some test helpers for functional specs. In order to
use them, you need to include Devise in your functional tests by
adding the following to the bottom of your test/test_helper.rb file
(make sure you place it out of scope of ActiveSupport::TestCase which
is the default class inside of test/test_helper.rb):
class ActionController::TestCase
include Devise::TestHelpers
end
Just be sure that this inclusion is made after the require
'rspec/rails' directive.
Now you are ready to use the sign_in and sign_out methods. Such
methods have the same signature as in controllers:
sign_in :user, @user # sign_in(scope, resource)
sign_in @user # sign_in(resource)
sign_out :user # sign_out(scope)
sign_out @user # sign_out(resource)
否则,current_user
将正确地变为 nil
。如果你想让你的代码容忍这个,那么你应该在视图中用 unless current_user.nil?
之类的东西来保护那个位。我还看到有人创建了一个 current_user_or_guest
方法来代替他们对 current_user
.
的使用
在助手中,他们创建了这样的东西:
def current_or_guest_user
if current_user
current_user
else
User.new
end
end
编辑:
在 Michael Hartl's Rails tutorial 中,它不使用 Devise,而是让您创建一个 current_user
方法,如下所示:
def current_user
User.find_by(id: session[:user_id])
end
当没有session[:user_id]
时,这个current_user
方法会returnnil
。在 current_user
不再 return nil
之前,您仍然需要对用户进行身份验证。 test/integration/users_login_test.rb
.
中已有测试用户认证测试的代码
因此,在您的测试中,您需要确保执行类似 log_in User.find_by(id: <some valid ID>)
的操作来验证用户身份。这将确保 current_user
像在正常使用上下文中一样执行。
您可以添加一个 test/support
目录,并在该目录中创建 login_helpers.rb
:
def log_in_with(email,password) do
get login_path
post login_path, session: { email: email, password: password }
end
然后,为确保这些方法可用,在您的 test/test_helper.rb
中添加:
Dir[Rails.root.join('test/support/**/*.rb')].each { |f| require f }
现在,在需要经过身份验证的用户的测试中,执行:
log_in_with('a_valid_email', 'its valid password')
我完成了 Michael Hartl 的 Rails 教程的第 11 章,之后我开始寻找使用 thumbs_up gem 为微博添加一些声誉和投票功能的方法。
我想在导航栏的小方框(如 Stack Overflow)中显示当前用户的声誉。我可以使用以下方法获得用户名和信誉以正常显示:
<li class="rep_box"><%= current_user.name %> <%= current_user.karma %> </li>
该页面工作正常并正确呈现用户名和声誉,但现在我遇到了几个错误并失败了。如果我删除上面的代码行,一切都会再次正常工作。
这是错误的一个例子——它们几乎都是一样的:
>ERROR["test_should_get_home", StaticPagesControllerTest, 2016-04-09 04:36:31 -0400]
test_should_get_home#StaticPagesControllerTest (1460190991.59s)
ActionView::Template::Error: ActionView::Template::Error: undefined method `name' for nil:NilClass
app/views/layouts/_header.erb:6:in `_app_views_layouts__header_erb__1475229759153232172_2241208160'
app/views/layouts/application.html.erb:12:in `_app_views_layouts_application_html_erb__4357373253304461109_2216429940'
test/controllers/static_pages_controller_test.rb:9:in `block in <class:StaticPagesControllerTest>'
app/views/layouts/_header.erb:6:in `_app_views_layouts__header_erb__1475229759153232172_2241208160'
app/views/layouts/application.html.erb:12:in `_app_views_layouts_application_html_erb__4357373253304461109_2216429940'
test/controllers/static_pages_controller_test.rb:9:in `block in <class:StaticPagesControllerTest>'
undefined method `name' for nil:NilClass
这意味着 current_user
在调用 name
时是 nil
。确保此时已正确分配,错误就会消失。
你需要sign_in
一个用户才有current_user
.
你可以这样做:
let(:curr_user) { User.create(...attrs...) }
sign_in curr_user
Devise includes some test helpers for functional specs. In order to use them, you need to include Devise in your functional tests by adding the following to the bottom of your test/test_helper.rb file (make sure you place it out of scope of ActiveSupport::TestCase which is the default class inside of test/test_helper.rb):
class ActionController::TestCase include Devise::TestHelpers end
Just be sure that this inclusion is made after the require 'rspec/rails' directive.
Now you are ready to use the sign_in and sign_out methods. Such methods have the same signature as in controllers:
sign_in :user, @user # sign_in(scope, resource) sign_in @user # sign_in(resource) sign_out :user # sign_out(scope) sign_out @user # sign_out(resource)
否则,current_user
将正确地变为 nil
。如果你想让你的代码容忍这个,那么你应该在视图中用 unless current_user.nil?
之类的东西来保护那个位。我还看到有人创建了一个 current_user_or_guest
方法来代替他们对 current_user
.
在助手中,他们创建了这样的东西:
def current_or_guest_user
if current_user
current_user
else
User.new
end
end
编辑:
在 Michael Hartl's Rails tutorial 中,它不使用 Devise,而是让您创建一个 current_user
方法,如下所示:
def current_user
User.find_by(id: session[:user_id])
end
当没有session[:user_id]
时,这个current_user
方法会returnnil
。在 current_user
不再 return nil
之前,您仍然需要对用户进行身份验证。 test/integration/users_login_test.rb
.
因此,在您的测试中,您需要确保执行类似 log_in User.find_by(id: <some valid ID>)
的操作来验证用户身份。这将确保 current_user
像在正常使用上下文中一样执行。
您可以添加一个 test/support
目录,并在该目录中创建 login_helpers.rb
:
def log_in_with(email,password) do
get login_path
post login_path, session: { email: email, password: password }
end
然后,为确保这些方法可用,在您的 test/test_helper.rb
中添加:
Dir[Rails.root.join('test/support/**/*.rb')].each { |f| require f }
现在,在需要经过身份验证的用户的测试中,执行:
log_in_with('a_valid_email', 'its valid password')