我的测试因ActionView :: Template :: Error而失败:未定义的方法`name'为零:NilClass错误?

时间:2016-12-16 11:32:15

标签: ruby-on-rails

此错误的原因是我的索引页面中的代码<%= pin.user.name %>

但当我将其更改为<%= pin.user.name if pin.user %>时,我的测试全部通过了。

Same question已经发布,但没有公认的解决方案,这就是我发布此帖的原因。

这是完整的错误消息:

ERROR["test_non-signed_in_user_layout_links", SiteLayoutTest, 1.3199719070007632]
 test_non-signed_in_user_layout_links#SiteLayoutTest (1.32s)
ActionView::Template::Error:         ActionView::Template::Error: undefined method `name' for nil:NilClass
            app/views/pins/_pin.html.erb:2:in `_app_views_pins__pin_html_erb___3167554587389080103_47088431630420'
            app/views/static_pages/home.html.erb:6:in `_app_views_static_pages_home_html_erb___4092361779176196837_47088431162360'
            test/integration/site_layout_test.rb:10:in `block in <class:SiteLayoutTest>'

ERROR["test_signed_in_user_layout_links", SiteLayoutTest, 2.0834625150000647]
 test_signed_in_user_layout_links#SiteLayoutTest (2.08s)
ActionView::Template::Error:         ActionView::Template::Error: undefined method `name' for nil:NilClass
            app/views/pins/_pin.html.erb:2:in `_app_views_pins__pin_html_erb___3167554587389080103_47088457226940'
            app/views/static_pages/home.html.erb:6:in `_app_views_static_pages_home_html_erb___4092361779176196837_47088457198480'
            test/integration/site_layout_test.rb:24:in `block in <class:SiteLayoutTest>'

ERROR["test_should_get_home", StaticPagesControllerTest, 2.1026109900003576]
 test_should_get_home#StaticPagesControllerTest (2.10s)
ActionView::Template::Error:         ActionView::Template::Error: undefined method `name' for nil:NilClass
            app/views/pins/_pin.html.erb:2:in `_app_views_pins__pin_html_erb___3167554587389080103_47088457310920'
            app/views/static_pages/home.html.erb:6:in `_app_views_static_pages_home_html_erb___4092361779176196837_47088457291840'
            test/controllers/static_pages_controller_test.rb:9:in `block in <class:StaticPagesControllerTest>'

这些是出现上述错误的测试:

  

site_layout_test.rb

require 'test_helper'

class SiteLayoutTest < ActionDispatch::IntegrationTest
  def setup
    ActionMailer::Base.deliveries.clear
    @user = users(:john)
  end

  test "non-signed in user layout links" do
    get root_path
    assert_template 'static_pages/home'
    assert_select "a[href=?]", root_path, count: 2
    assert_select "a[href=?]", about_path
    assert_select "a[href=?]", new_user_session_path, count: 2
    assert_select "a[href=?]", new_user_registration_path, count: 1
  end

  test "signed in user layout links" do
    get new_user_session_path
    assert_template 'devise/sessions/new'
    post user_session_path, params: { user: { email: @user.email, password: 'password' } }
    assert_not flash.empty?
    assert_redirected_to root_path
    follow_redirect!
    assert_template 'static_pages/home'
    assert_select "a[href=?]", new_user_session_path, count: 0
    assert_select "a[href=?]", new_user_registration_path, count: 0
    assert_select "a[href=?]", edit_user_registration_path
    assert_select "a[href=?]", destroy_user_session_path
    assert_select "a[href=?]", new_pin_path
  end
end
  

static_pages_controller_test.rb

require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  def setup
    @user = users(:john)
  end

  test "should get home" do
    get root_url
    assert_response :success
    assert_select "title", full_title
  end

  test "should get about" do
    get about_url
    assert_response :success
    assert_select "title", full_title("About")
  end
end

这些是我的users.yml

john:
  name: John Rockefeller
  email: john@rockefeller.com
  encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %>
  created_at: <%= Time.zone.now %>

andrew:
  name: Andrew Carnegie
  email: andrew@carnegie.com
  encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %>
  created_at: <%= Time.zone.now %>

pins.yml

quote:
  description: "Lorem quote"
  created_at: <%= 10.minutes.ago %>
  user: john

recipe:
  description: "Lorem recipe"
  created_at: <%= 3.years.ago %>

most_recent:
  description: "Lorem most recent"
  created_at: <%= Time.zone.now %>

1 个答案:

答案 0 :(得分:0)

如果您针对该代码段抛出binding.pry(假设您有pry / byebug)并在该情况下键入pin.user,则应该说nil

当您尝试在.name上致电nil时,您会收到错误。 if语句为您节省费用的原因是,如果.name为零,则不会调用pin.user

在rails中非常方便的修复方法是将代码更改为:

<%= pin.user.try(:name) %>,如果nilpin.user,则不会引发错误,但只会返回nil

可选地 -

如果您总是希望用户连接到某个引脚,则可以通过在创建之前验证用户是否与该引脚相关联来阻止无用户引脚存在:< / p>

class Pin < ActiveRecord::Base

  validates :user, presence: true

end

希望这有帮助!! :)