Rails ActionView :: Template ::错误:Nill类的未定义方法

时间:2015-05-07 19:19:02

标签: ruby-on-rails ruby unit-testing devise

我知道这是一个非常常见的问题,但其他任何回复都无法帮助我。

我目前正在尝试为我的网站创建测试,但我总是收到错误

  

ActionView :: Template ::错误:未定义的方法

我的很多方法通常会产生Nill类。该网站使用设计登录。

这是我正在尝试运行的测试。我确保我的灯具已装入测试数据库

    require 'test_helper'

class PagesControllerTest < ActionController::TestCase
  include Devise::TestHelpers
  include Warden::Test::Helpers
  Warden.test_mode!

  def setup
    sign_in User.first
  end

  def teardown
    Warden.test_reset!
  end

  test "should get index" do
    get :index
    assert_response :success
  end


  test "should get voting" do
    get :voting
    assert_response :success
  end
end

这些是尝试运行测试时的错误消息

Minitest::UnexpectedError: ActionView::Template::Error: undefined method `strip' for nil:NilClass
    config/initializers/addChallenges.rb:22:in `findChallenges'
    app/views/pages/index.html.erb:11:in `_app_views_pages_index_html_erb__190802989_69818040'
    test/controllers/pages_controller_test.rb:18:in `block in <class:PagesControllerTest>'
config/initializers/addChallenges.rb:22:in `findChallenges'
app/views/pages/index.html.erb:11:in `_app_views_pages_index_html_erb__190802989_69818040'
test/controllers/pages_controller_test.rb:18:in `block in <class:PagesControllerTest>'

Minitest::UnexpectedError: ActionView::Template::Error: undefined method `strip' for nil:NilClass
    config/initializers/addIdeas.rb:25:in `findIdeas'
    app/views/pages/voting.html.erb:6:in `_app_views_pages_voting_html_erb___557022735_70668940'
    test/controllers/pages_controller_test.rb:24:in `block in <class:PagesControllerTest>'
config/initializers/addIdeas.rb:25:in `findIdeas'
app/views/pages/voting.html.erb:6:in `_app_views_pages_voting_html_erb___557022735_70668940'
test/controllers/pages_controller_test.rb:24:in `block in <class:PagesControllerTest>'
Finished in 0.31402s
2 tests, 0 assertions, 0 failures, 2 errors, 0 skips

Process finished with exit code 0

在这种情况下跟踪错误时,此行显示为有问题resp = http.get(url.path, headers)这是我的完整addIdeas代码,但addChallenges代码非常相似。

class AddIdeas
  #a method that will find all the challenge ideas for a user and then store them in our databse
  def self.findIdeas(email,challengeId)

    require "net/http"
    require "uri"
    require 'json'
    require 'active_record'

    p= People.find_by_email(email)

    uri_string = 'http://sideways6.com/api/V1/Idea/Challenge/'
    uri_string << challengeId.to_s

    #make the http request with the headers
    url = URI.parse(uri_string)
    http = Net::HTTP.new(url.host, url.port)
    headers = {
        'Authorization' => p.basic,
        'UserId' => p.userId,
        'AuthorizationToken' => p.auth_tok
    }

    #retrieve a get response
    resp = http.get(url.path, headers)
    #if response is okay parse the challenge ids and add them to the person table for that user
    if resp.code.to_s == '200'
        if resp.body.to_s != 'null'
          puts parsed = JSON.parse(resp.body)
          ids = ""
          parsed.each do |element|
            addIdeas(element, challengeId)
            ids << "#{element['IdeaId']},"
          end
          c = Challenges.find_by_challengeId(challengeId)
          c.ideaIds = ids
          c.save
        end
    end
  end

  def self.addIdeas(element, challengeId)
    i = Ideas.find_by_ideaId(element['IdeaId'])

    if i == nil
      i = Ideas.create(:ideaId => element['IdeaId'], :title => element['Title'], :description => element['Description'], :challengeIds => challengeId, :score=>1000, :faceOff => 0, :wins =>0)
    end
    if i != nil
      i.ideaId = (element['IdeaId'])
      i.title = (element['Title'])
      i.description = (element['Description'])
      i.challengeIds = challengeId
      i.save
    end
  end


  def self.findAllIdeas(email)
    p = People.find_by_email(email)
    ids = p.challenges
    splitted = ids.split(",")
    counter = splitted.length
    i =0
    while i < counter.to_i do
      findIdeas(email, splitted[i])
      i += 1
    end
  end
end

addChallenges文件

class AddChallenges
  #a method that will find all the challenge ideas for a user and then store them in our databse
  def self.findChallenges(email)

    require "net/http"
    require "uri"
    require 'json'
    require 'active_record'

    p= People.find_by_email(email)

    #make the http request with the headers
    url = URI.parse('http://sideways6.com/api/V1/Challenge/All')
    http = Net::HTTP.new(url.host, url.port)
    headers = {
        'Authorization' => p.basic,
        'UserId' => p.userId,
        'AuthorizationToken' => p.auth_tok
    }

    #retrieve a get response
    resp = http.get(url.path, headers)
    #if response is okay parse the challenge ids and add them to the person table for that user
    if resp.code.to_s == '200'
      puts parsed = JSON.parse(resp.body)
      ids = ""
      parsed.each do |element|
        addChallenges(element)
        ids << "#{element['ChallengeId']},"
      end

      p = People.find_by_email(email)
      p.challenges = ids
      p.save
    end
  end

  def self.addChallenges(element)
    c = Challenges.find_by_challengeId(element['ChallengeId'])
    if c == nil
      c = Challenges.create(:challengeId => element['ChallengeId'], :title => element['Title'], :description => element['Description'])
    end
    if c != nil
      c.challengeId = (element['ChallengeId'])
      c.title = (element['Title'])
      c.description = (element['Description'])
      c.save
    end
  end

  def self.retrieveChallengeObject(challengeId)
    c = Challenges.find_by_challengeId(challengeId)
  end

end

我的页面控制器按要求

class PagesController <ApplicationController

  def home
    @current_nav_identifier = :home
  end
end

索引页

<script type="text/javascript">window._token = '<%= form_authenticity_token %>';</script>
<body>
<noscript>
  <div class='warning-page-cover'>
    <div class='alert alert-info'>
      <h2>Sorry about that, it appears that you are using a web browser without JavaScript which prevents us offering you a rich online experience.</h2>
      <p>Please enable JavaScript or use a different web browser, or alternatively contact the CiCS Helpdesk for assistance.</p>
    </div>
  </div>
</noscript>
<%AddChallenges.findChallenges(current_user.email)%>
<%AddIdeas.findAllIdeas(current_user.email)%>

<div id='wrap'>
  <nav class='navbar navbar-default navbar-fixed-top' id='main-nav'>
    <div class='container-fluid'>

      <div class='navbar-header'>
        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
          <span class="sr-only">Toggle navigation</span>
          <span class='icon-bar'></span>
          <span class='icon-bar'></span>
          <span class='icon-bar'></span>
        </button>
        <a href="<%= url_for(:controller=> 'pages', :action => 'index')%>">
          <%= image_tag('/logo.png', :alt => "Sideways 6 Logo", size:"203x50") %>
        </a>
      </div>
      <div class='collapse navbar-collapse'  id="bs-example-navbar-collapse-1">
        <ul class='nav navbar-nav'>
        </ul>
        <% if true # user_signed_in? %>
            <ul class="nav navbar-nav navbar-right">
              <li><%= link_to fa_icon('index', text: 'Refresh Challenges'), root_path  ,  method: :get %></li>
              <li class="dropdown">
                <%= link_to '#', data: { toggle: :dropdown }, class: 'dropdown-toggle' do %>
                    <span class="glyphicon glyphicon-user" aria-hidden="true"></span>
                    <% p = People.find_by_email(current_user.email)%>
                    <% fName = p.firstName %>
                    <% if fName != nil %>
                        <%= fa_icon('user', text: fName )%>
                    <%end%>
                    <% if fName == nil %>
                        <%= fa_icon('user', text: current_user.email) %>
                    <%end%>
                    <b class="caret"></b>

                <% end %>

                <ul class="dropdown-menu">
                  <li>
                    <%# log out path is usually: destroy_user_session_path %>
                    <%= link_to fa_icon('index',  text: Score.retrieveUserScore(current_user.email)), root_path , method: :get %>
                    <%= link_to fa_icon('challenges', text:'All Challenges'), challenges_path, method: :get, title: "See all Challenges"  %>
                    <%= link_to fa_icon('sign-out', text: 'Log out'), destroy_user_session_path, method: :get, title: "Log out of the system" %>
                  </li>
                </ul>
              </li>
            </ul>
        <% end %>
      </div>

    </div>
  </nav>
    <div id="main">
      <h1>Select A Challenge To Vote On</h1>
      <% p = People.find_by_email(current_user.email)  %>
      <% ids = p.challenges %>
      <% splitted = ids.split(",") %>
      <% counter = splitted.length %>


      <p class="lead">Please Select One</p>
      <% i =0 %>
      <% while i < counter.to_i do %>
      <div class="row">

        <div class="col-xs-12 col-md-6">
          <% c = AddChallenges.retrieveChallengeObject(splitted[i]) %>
          <% if Vote.canVote(splitted[i]) == true %>
          <a href="<%= url_for(:controller=> 'pages', :action => 'voting')%>?challengeId=<%=(splitted[i])%>" class="challenge-select" data-challengeid="<%=(splitted[i])%>">
            <div class="well clickable">
                <h4><%= c.title %></h4>
                <p class="text-center"> <%= c.description %> </p>
            </div>
          </a>
           <% end %>
        </div>
        <% i+=1 %>
        <% if i != counter %>
        <div class="col-xs-12 col-md-6">
          <% c = AddChallenges.retrieveChallengeObject(splitted[i]) %>
          <% if Vote.canVote(splitted[i]) == true %>
          <a href="<%= url_for(:controller=> 'pages', :action => 'voting')%>?challengeId=<%=(splitted[i])%>" class="challenge-select" data-challengeid="<%=(splitted[i])%>">
          <div class="well clickable">
            <h4><%= c.title %></h4>
            <p class="text-center"><%= c.description %></p>
          </div>
          </a>
          <% end %>
        </div>
        <%end%>
    </div>
          <% i+=1 %>
      <%end%>

    <%= yield %>
  </div>
</div>

投票html

<script type="text/javascript">window._token = '<%= form_authenticity_token %>';</script>

<% require 'digest/sha1'
    salt = '%+5)_' %>

<% AddIdeas.findIdeas(current_user.email,params[:challengeId]) %>

<% if params[:winner] != nil
    concat = "#{salt}#{params[:challengeId]}#{params[:winner]}#{params[:loser]}#{salt}"
    hash = Digest::SHA1.hexdigest(concat)
    if hash == params[:hash]
        Score.updateScore(params[:winner],params[:loser])
        Score.userScore(current_user.email)
    end
end %>
<div id='wrap'>
  <nav class='navbar navbar-default navbar-fixed-top' id='main-nav'>
    <div class='container-fluid'>

      <div class='navbar-header'>
        <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
          <span class="sr-only">Toggle navigation</span>
          <span class='icon-bar'></span>
          <span class='icon-bar'></span>
          <span class='icon-bar'></span>
        </button>
        <a href="<%= url_for(:controller=> 'pages', :action => 'index')%>">
          <%= image_tag('/logo.png', :alt => "Sideways 6 Logo", size:"203x50") %>
        </a>
      </div>
      <div class='collapse navbar-collapse'  id="bs-example-navbar-collapse-1">
        <ul class='nav navbar-nav'>
        </ul>
        <% if true # user_signed_in? %>
            <ul class="nav navbar-nav navbar-right">
              <li><%= link_to fa_icon('index', text: 'Change Challenge'), root_path  ,  method: :get %></li>

              <li class="dropdown">
                <%= link_to '#', data: { toggle: :dropdown }, class: 'dropdown-toggle' do %>
                    <span class="glyphicon glyphicon-user" aria-hidden="true"></span>
                    <% p = People.find_by_email(current_user.email)%>
                    <% fName = p.firstName %>
                    <% if fName != nil %>
                        <%= fa_icon('user', text: fName )%>
                    <%end%>
                    <% if fName == nil %>
                        <%= fa_icon('user', text: current_user.email) %>
                    <%end%>
                    <b class="caret"></b>

                <% end %>

                <ul class="dropdown-menu">
                  <li>
                    <%# log out path is usually: destroy_user_session_path %>
                    <%= link_to fa_icon('index',  text: Score.retrieveUserScore(current_user.email)), root_path , method: :get %>
                    <%= link_to fa_icon('challenges', text:'All Challenges'), challenges_path, method: :get, title: "See all Challenges"  %>
                    <%= link_to fa_icon('sign-out', text: 'Log out'), destroy_user_session_path, method: :get, title: "Log out of the system" %>
                  </li>
                </ul>
              </li>
            </ul>
        <% end %>
      </div>

    </div>
  </nav>
  <div id="main">
    <% c = Challenges.find_by_challengeId(params[:challengeId]) %>
    <% ids = c.try(:ideaIds) %>
    <% splitted = ids.try(:split, ",") %>
    <% shuffle = splitted.try(:shuffle) %>
    <% firstIdea = shuffle.try(:first) %>
    <% lastIdea = shuffle.try(:last) %>
    <% f = Ideas.find_by_ideaId(firstIdea)%>
    <% l = Ideas.find_by_ideaId(lastIdea)%>
    <h1><%=c.try(:title)%></h1>
    <p class="lead">Which best solves the challenge?</p>
    <div class="row">
      <div class="col-xs-12 col-md-6">
        <% challengeId = params[:challengeId]
        winner = f.try(:ideaId)
        loser = l.try(:ideaId)
        concat = "#{salt}#{challengeId}#{winner}#{loser}#{salt}"
        hash = Digest::SHA1.hexdigest(concat) %>
        <a href="<%= url_for(:controller=> 'pages', :action => 'voting')%>?challengeId=<%=(params[:challengeId])%>&winner=<%=(f.try(:ideaId))%>&loser=<%=(l.try(:ideaId))%>&hash=<%=(hash)%>" class="idea-vote" data-challengeid="<%=(params[:challengeId])%>" data-winner="<%=(f.try(:ideaId))%>" data-loser="<%=(l.try(:ideaId))%>" data-hash="<%=(hash)%>">
        <div class="well clickable">
          <h4><%= f.try(:title) %></h4>
          <p class="text-center"><%= f.try(:description)%></p>
        </div>
        </a>
      </div>
      <div class="col-xs-12 col-md-6">
        <% challengeId = params[:challengeId]
        winner = l.try(:ideaId)
        loser = f.try(:ideaId)
        concat = "#{salt}#{challengeId}#{winner}#{loser}#{salt}"
        hash = Digest::SHA1.hexdigest(concat) %>
        <a href="<%= url_for(:controller=> 'pages', :action => 'voting')%>?challengeId=<%=(params[:challengeId])%>&winner=<%=(l.try(:ideaId))%>&loser=<%=(f.try(:ideaId))%>&hash=<%=(hash)%>" class="idea-vote" data-challengeid="<%=(params[:challengeId])%>" data-winner="<%=(l.try(:ideaId))%>" data-loser="<%=(f.try(:ideaId))%>" data-hash="<%=(hash)%>">
        <div class="well clickable">
          <h4><%=l.try(:title)%></h4>
          <p class="text-center"><%=l.try(:description)%></p>
        </div>
        </a>
      </div>
    </div>
    <a href="<%= url_for(:controller=> 'pages', :action => 'voting')%>?challengeId=<%=(params[:challengeId])%>" class="btn btn-default btn-sm">Skip <span class="glyphicon glyphicon-chevron-right"></span></a>
    <%= yield %>
  </div>
</div>

我尝试使用try()修改方法,似乎有时会解决问题,但之后try()会导致网站本身出现问题。有时,错误消息会将我重定向到使用方法的html视图文件本身。

编辑: 修好标题后我现在好了

Minitest::UnexpectedError: ActionView::Template::Error: undefined method `split' for nil:NilClass
    config/initializers/addIdeas.rb:61:in `findAllIdeas'
    app/views/pages/index.html.erb:12:in `_app_views_pages_index_html_erb__1448445017_66568380'
    test/controllers/pages_controller_test.rb:17:in `block in <class:PagesControllerTest>'
config/initializers/addIdeas.rb:61:in `findAllIdeas'
app/views/pages/index.html.erb:12:in `_app_views_pages_index_html_erb__1448445017_66568380'
test/controllers/pages_controller_test.rb:17:in `block in <class:PagesControllerTest>'

Minitest::UnexpectedError: ActionView::Template::Error: undefined method `score' for #<People:0x000000085d17b0>
    config/initializers/score.rb:50:in `retrieveUserScore'
    app/views/pages/voting.html.erb:56:in `_app_views_pages_voting_html_erb___944539514_69504160'
    test/controllers/pages_controller_test.rb:23:in `block in <class:PagesControllerTest>'
config/initializers/score.rb:50:in `retrieveUserScore'
app/views/pages/voting.html.erb:56:in `_app_views_pages_voting_html_erb___944539514_69504160'
test/controllers/pages_controller_test.rb:23:in `block in <class:PagesControllerTest>'
Finished in 0.53103s
2 tests, 0 assertions, 0 failures, 2 errors, 0 skips

Process finished with exit code 0

score.rb文件

class Score
  def self.updateScore(winner, loser)
    Math.exp(1)
    w = Ideas.find_by_ideaId(winner)
    l = Ideas.find_by_ideaId(loser)
    # updatewinner
    # games W played = get number of times the winner has matched up against other ideas
    # winner new score = winner score + (1000/games W played) (1+ 1/(1 + Math.exp(loser score - winner score)))
    w.faceOff += 1
    w.save

    lScore = l.score
    wScore = w.score
    wGames = w.faceOff

    newWScore = wScore + (500/wGames)*(1-(1/(1 + Math.exp(lScore - wScore))))

    l.faceOff += 1
    l.save
    lGames = l.faceOff

    newLScore = lScore + (500/lGames)*(-1/(1+ Math.exp(wScore - lScore)))

    puts "New Winner Score "
    puts newWScore
    w.score = newWScore
    w.save

    puts "New Loser Score "
    puts newLScore
    l.score = newLScore
    l.save

    puts newWScore
    # updateloser
    # games L played = get number of times the loser has matched up against other ideas
    # loser new score = loser score + (1000/games L played) (1+ 1/(Math.exp(winner score - loser score)))
  end

  def self.userScore(email)
    p = People.find_by_email(email)
    score = p.score
    newScore = score + 1
    p.score = newScore
    p.save
  end

  def self.retrieveUserScore(email)
    p = People.find_by_email(email)
    score = 'Score: ' << p.score.to_s

  end

end

1 个答案:

答案 0 :(得分:1)

好的,我做了一些测试:

您的错误是header参与者之一以[{1}}

从您的数据库返回

我可以通过设置

来复制您的错误
nil

并运行headers = { 'Authorization' => nil, 'UserId' => nil, 'AuthorizationToken' => nil }

你可以做些什么来避免异常,让API返回错误是测试nil并用空字符串替换http.get(url.path, headers)

例如:""

编辑:对于您上面的编辑...

有两个错误:

  1. 'Authorization' => p.basic || ""
    这是因为:

    ActionView::Template::Error: undefined method 'split' for nil:NilClass
     ids = p.challenges

  2. 如果ID为零,则无法在其上调用splitted = ids.split(",")。您需要在此时添加一个检查并返回。

    1. split
    2. 您的ActionView::Template::Error: undefined method 'score' for #<People:0x000000085d17b0>模型没有People方法